pax_global_header00006660000000000000000000000064136066757570014540gustar00rootroot0000000000000052 comment=bb8a5182e634ef9690234b39c8bb972ad92f5039 jasypt-jasypt-1.9.3/000077500000000000000000000000001360667575700143745ustar00rootroot00000000000000jasypt-jasypt-1.9.3/CONTRIBUTING.md000066400000000000000000000345721360667575700166400ustar00rootroot00000000000000Contributing to Jasypt: Terms and Conditions =============================================== ------------------------------------------------------------------------------ Do you want to contribute your work to Jasypt? Well, then first and most important: **THANK YOU!** Now, in order to accept your contribution, there are some terms you must expressly agree with, so please read them carefully. They may seem a bit cumbersome but they are there to protect you, your contribution, and most importantly, the project's future. **Important**: submitting any contributions to the Jasypt project implies your **full acceptance of these terms**, including the *"Jasypt Individual Contributor License Agreement"* detailed at the end of this document. Who can contribute? ------------------- Anyone, with the unique condition that he/she must be a **private individual**, acting in his/her own name, and not being endorsed in their contributed work by any company or government. Note that this condition will not only refer to the ownership of the effort invested in contributing to the project, but also to the fact that *no private or public company will be mentioned as a part of your contribution on the project's website or code*, including but not limited to web/email addresses or package names. What is the first step to be taken? ----------------------------------- First of all, **talk to the [project members](http://www.jasypt.org/team.html)** (an email should do) about your ideas: new features, fixes, documentation... whatever you would like to contribute to the project. Let us discuss the possibilities with you so that we make sure your contribution goes in the right direction and aligns with the project's standards, intentions and roadmap. How will your involvement with the Jasypt project work? ---------------------------------------------------------- All contributions are submitted in the form of GitHub *pull requests*. Note that contributors do not have read+write (or *pull+push*) access to the project repositories, only project *members* do. Also, please understand that *not all pull requests will be accepted and merged into the project's repositories*. Talk about your planned contributions with the project members before creating pull requests so you can maximize the possibility of your contributions being accepted. Once your contribution is approved, you will be listed as a *contributor* on the [Jasypt Team page](http://www.jasypt.org/team.html). You can opt-out of this if you want. Also, you will be `@author` for any new Java classes that you write and also co-`@author` of any existing classes to which you make significant changes. You can also opt-out of this if you want. About the code you contribute ----------------------------- ### General guidelines: - Obviously, **your code must both compile and work correctly**. Also, the addition of any new patches to the codebase should not render it unstable in any way. - All your code should be easy to read and understand by a human. - There should be no compilation warnings at all. ### Detailed Java code quality standards: - All your code should compile and run in **Java 6.0**. - All comments, names of classes and variables, log messages, etc. must be **in English**. - All `.java` files must include the standard Jasypt copyright header. - All your code should follow the Java Code Conventions regarding variable/method/class naming. - Maximum line length is 120 characters. - Indentation should be made with 4 spaces, not tabs. - Line feeds should be UNIX-like (`\n`). - All `.java` source files should be pure ASCII. All `.properties` files should be ISO-8859-1. - Number autoboxing and/or autounboxing is forbidden. - Every class should define a constructor, even if it is the no-argument constructor, and include a call to `super()`. - All method parameters should be declared as `final` so that they cannot be changed or reassigned in the method. - All non-nullable parameters in a public method should be first validated with a `Validate.notNull(...)` call. This maintains consistency in the behavior of public methods and the error message used. - Include a block comment (`/* ... */`) for any non-trivial algorithm you develop. *"Non-trivial"* usually means you had to make some design decisions to do things in a certain way. Your comment should explain *why* you wrote the code the way you wrote it. Do not write obvious comments that explain what the code does; the code should be clear and expressive enough so the *what* and *how* of it is obvious. - All public methods and classes directly available to users should have comprehensive JavaDoc comments. ### Detailed HTML/XML code quality standards: - All tags, CSS styles, file names, etc. must be **in English**. - Lower case should be preferred for HTML/XML artifacts. The only exceptions are `DOCTYPE` and `CDATA` clauses. - All HTML code should be XML-valid (i.e. all tags should be closed, attributes surrounded by commas, etc.) - Maximum line length is 120 characters. - Indentation should be made with 4 spaces, not tabs. - Line feeds should be UNIX-like (`\n`). - All `.html` and `.xml` source files should be pure ASCII, even if _content-type_ is set to a different encoding. - All XHTML self-closing (minimized) tags should have a space before `/>` (the XHTML standards say so!). - All inline scripts must be enclosed inside a commented `` block. About the documentation/articles you contribute ----------------------------------------------- Note the following only applies to documentation/articles meant to be published at the Jasypt website. - All documentation artifacts, including articles, must be written **in correct English**. - Your name and email will be displayed as *"author"* of any documentation artifacts you create. - Topic and text structure must be first discussed and agreed upon with the project members. - Project members may edit and make small changes to your texts—of which you will be informed—before publishing them. - Format and visual styles must adhere to the Jasypt website standards, of which you will be informed by the project members. Pay special attention to this ----------------------------- All Jasypt software is distributed under the **Apache License 2.0** open source license; your contributions will be licensed in the same way. If you work for a company which, by the way or place in which your code was written, by your contract terms or by the laws in your country, could claim any rights (including but not limited to intellectual or industrial property) over your contributed code, you will have to send the project members (either by email from your authorised superiors or by signed fax), a statement indicating that your company agrees with the terms explained in this page, and that it both authorises your contribution to Jasypt and states that it will never claim any kind of rights over it. Jasypt Individual Contributor License Agreement -------------------------------------------------- This contributor agreement ("Agreement") documents the rights granted by contributors to the Jasypt Project. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Jasypt. ### 1. Definitions * _"Jasypt"_ means the "Jasypt Project organization and members". * _"You"_ means the individual who submits a Contribution to Jasypt. * _"Contribution"_ means any work of authorship that is submitted by you to Jasypt in which you own or assert ownership of the Copyright. * _"Copyright"_ means all rights protecting works of authorship owned or controlled by you, including copyright, moral and neighboring rights, as appropriate, for the full term of their existence including any extensions by you. * _"Material"_ means the work of authorship which is made available by Jasypt to third parties. When this Agreement covers more than one software project, the Material means the work of authorship to which the Contribution was submitted. After you submit the Contribution, it may be included in the Material. * _"Submit"_ means any form of electronic, verbal, or written communication sent to Jasypt or its representatives, including but not limited to electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Jasypt for the purpose of discussing and improving the Material, but excluding communication that is conspicuously marked or otherwise designated in writing by you as _"Not a Contribution."_ * _"Submission Date"_ means the date on which you submit a Contribution to Jasypt. * _"Effective Date"_ means the date you execute this agreement or the date You first submit a Contribution to Jasypt, whichever is earlier. ### 2. Grant of Rights #### 2.1. Copyright License * (a) You retain ownership of the copyright in your Contribution and have the same rights to use or license the Contribution which you would have had without entering into the agreement. * (b) To the maximum extent permitted by the relevant law, you grant to Jasypt a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable license under the copyright covering the Contribution, with the right to sublicense such rights through multiple tiers of sublicensees, to reproduce, modify, display, perform and distribute the Contribution as part of the Material; provided that this license is conditioned upon compliance with Section 2.3. #### 2.2 Patent License For patent claims including, without limitation, method, process, and apparatus claims which you own, control or have the right to grant, now or in the future, you grant to Jasypt a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable patent license, with the right to sublicense these rights to multiple tiers of sublicensees, to make, have made, use, sell, offer for sale, import and otherwise transfer the Contribution and the Contribution in combination with the Material (and portions of such combination). This license is granted only to the extent that the exercise of the licensed rights infringes such patent claims; and provided that this license is conditioned upon compliance with Section 2.3. #### 2.3 Outbound License As a condition on the grant of rights in Sections 2.1 and 2.2, Jasypt agrees to license the Contribution only under the terms of the Apache License 2.0 (including any right to adopt any future version of this license if permitted). #### 2.4 Moral Rights If moral rights apply to the Contribution, to the maximum extent permitted by law, you waive and agree not to assert such moral rights against Jasypt or its successors in interest, or any of our licensees, either direct or indirect. #### 2.5 Jasypt Rights You acknowledge that Jasypt is not obligated to use your Contribution as part of the Material and may decide to include any Contributions Jasypt considers appropriate. #### 2.6 Reservation of Rights Any rights not expressly assigned or licensed under this section are expressly reserved by you. ### 3. Agreement You confirm that: * (a) You have the legal authority to enter into this Agreement. * (b) You own the Copyright and patent claims covering the Contribution which are required to grant the rights under Section 2. * (c) The grant of rights under Section 2 does not violate any grant of rights which you have made to third parties, including your employer. If you are an employee, you have had your employer approve this Agreement. If you are less than eighteen years old, please have your parents or guardian sign the Agreement. ### 4. Disclaimer EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, THE CONTRIBUTION IS PROVIDED "AS IS". MORE PARTICULARLY, ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO JASYPT AND BY JASYPT TO YOU. TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW. ### 5. Consequential Damage Waiver TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU OR JASYPT BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL AND EXEMPLARY DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED. ### 6. Miscellaneous * 6.1 This Agreement will be governed by and construed in accordance with the laws of Spain excluding its conflicts of law provisions. Under certain circumstances, the governing law in this section might be superseded by the United Nations Convention on Contracts for the International Sale of Goods ("UN Convention") and the parties intend to avoid the application of the UN Convention to this Agreement and, thus, exclude the application of the UN Convention in its entirety to this Agreement. * 6.2 This Agreement sets out the entire agreement between you and Jasypt for your Contributions to Jasypt and overrides all other agreements or understandings. * 6.3 If You or Jasypt assign the rights or obligations received through this Agreement to a third party, as a condition of the assignment, that third party must agree in writing to abide by all the rights and obligations in the Agreement. * 6.4 The failure of either party to require performance by the other party of any provision of this Agreement in one situation shall not affect the right of a party to require such performance at any time in the future. A waiver of performance under a provision in one situation shall not be considered a waiver of the performance of the provision in the future or a waiver of the provision in its entirety. * 6.5 If any provision of this Agreement is found void and unenforceable, such provision will be replaced to the extent possible with a provision that comes closest to the meaning of the original provision and which is enforceable. The terms and conditions set forth in this Agreement shall apply notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the maximum extent possible under law. jasypt-jasypt-1.9.3/LICENSE000066400000000000000000000261351360667575700154100ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/README.md000066400000000000000000000010041360667575700156460ustar00rootroot00000000000000JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort and without the need of having deep knowledge on how cryptography works. - Learn more: [http://www.jasypt.org](http://www.jasypt.org) - Download distributable: [jasypt 1.9.3 (binaries and javadocs)](https://github.com/jasypt/jasypt/releases/download/jasypt-1.9.3/jasypt-1.9.3-dist.zip) jasypt-jasypt-1.9.3/jasypt-acegisecurity/000077500000000000000000000000001360667575700205445ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/.gitignore000066400000000000000000000000721360667575700225330ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-acegisecurity/BUILD.txt000066400000000000000000000015521360667575700221470ustar00rootroot00000000000000 Building JASYPT-ACEGISECURITY ----------------------------- To build JASYPT-ACEGISECURITY you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-ACEGISECURITY project root folder: mvn clean:clean install And you will get a fresh target/jasypt-acegisecurity-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-acegisecurity/{version}/jasypt-acegisecurity-{version}.jar Generating Javadoc for JASYPT-ACEGISECURITY ------------------------------------------- If you wish to generate the javadoc for JASYPT-ACEGISECURITY, execute this from the JASYPT-ACEGISECURITY root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-acegisecurity/ChangeLog.txt000066400000000000000000000005611360667575700231360ustar00rootroot000000000000001.9.3 ===== - Deprecated in 1.9.3. This module will be removed in 2.0.0. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-acegisecurity package from previous monolithic jasypt module. - Renamed org.jasypt.spring.security2 package as org.jasypt.springsecurity2.providers.encoding, and deprecated the classes in the old package. jasypt-jasypt-1.9.3/jasypt-acegisecurity/LICENSE.txt000066400000000000000000000261361360667575700223770ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-acegisecurity/NOTICE.txt000066400000000000000000000072671360667575700223020ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-acegisecurity/README.txt000066400000000000000000000006111360667575700222400ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-acegisecurity/RELEASING.txt000066400000000000000000000023061360667575700226170ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-acegisecurity/USAGE.txt000066400000000000000000000012151360667575700221500ustar00rootroot00000000000000 Using JASYPT-ACEGISECURITY from Maven 2 --------------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-acegisecurity {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-acegisecurity/pom.xml000066400000000000000000000165511360667575700220710ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-acegisecurity jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.acegisecurity acegi-security 1.0.0 provided true javax.servlet servlet-api 2.4 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/000077500000000000000000000000001360667575700213335ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/000077500000000000000000000000001360667575700222575ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/000077500000000000000000000000001360667575700232005ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/000077500000000000000000000000001360667575700237675ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/000077500000000000000000000000001360667575700253015ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/acegisecurity/000077500000000000000000000000001360667575700301415ustar00rootroot00000000000000PBEPasswordEncoder.java000066400000000000000000000236331360667575700343650ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/acegisecurity/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.acegisecurity; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security (ACEGI) * org.acegisecurity.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in ACEGI using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security.PBEPasswordEncoder since 1.4) * * @author Daniel Fernández * * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class PBEPasswordEncoder implements org.acegisecurity.providers.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/acegisecurity/PasswordEncoder.java000066400000000000000000000222051360667575700341070ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.acegisecurity; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security (ACEGI) * org.acegisecurity.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security.PasswordEncoder since 1.4) * * @author Daniel Fernández * * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class PasswordEncoder implements org.acegisecurity.providers.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/spring/000077500000000000000000000000001360667575700266035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/spring/security/000077500000000000000000000000001360667575700304525ustar00rootroot00000000000000PBEPasswordEncoder.java000066400000000000000000000237561360667575700347040ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/spring/security/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security (ACEGI) * org.acegisecurity.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in ACEGI using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.4 (existed since 1.2 as * org.jasypt.springsecurity.PasswordEncoder) * * @deprecated Renamed as org.jasypt.acegisecurity.PBEPasswordEncoder. * Class will be removed from this package in 1.11. * * @author Daniel Fernández * */ public final class PBEPasswordEncoder implements org.acegisecurity.providers.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000223301360667575700343400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-acegisecurity/src/main/java/org/jasypt/spring/security/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security (ACEGI) * org.acegisecurity.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.4 (existed since 1.2 as * org.jasypt.springsecurity.PasswordEncoder) * * @deprecated Renamed as org.jasypt.acegisecurity.PasswordEncoder. * Class will be removed from this package in 1.11. * * @author Daniel Fernández * */ public final class PasswordEncoder implements org.acegisecurity.providers.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-dist/000077500000000000000000000000001360667575700166475ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/.gitignore000066400000000000000000000000721360667575700206360ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-dist/LICENSE.txt000066400000000000000000000261361360667575700205020ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-dist/NOTICE.txt000066400000000000000000000072671360667575700204050ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-dist/README.txt000066400000000000000000000006111360667575700203430ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-dist/pom.xml000066400000000000000000000207141360667575700201700ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-dist jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-site-plugin 2.1 org.apache.maven.plugins maven-assembly-plugin 2.2 make-assembly-dist package attached ${basedir}/src/assembly/dist.xml true jasypt-${project.version} org.apache.maven.plugins maven-project-info-reports-plugin 2.4 https://github.com/jasypt/jasypt/ scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git jasypt license scm org.jasypt jasypt ${project.version} compile org.jasypt jasypt-acegisecurity ${project.version} compile org.jasypt jasypt-hibernate3 ${project.version} compile org.jasypt jasypt-hibernate4 ${project.version} compile org.jasypt jasypt-hibernate5 ${project.version} compile org.jasypt jasypt-spring2 ${project.version} compile org.jasypt jasypt-spring3 ${project.version} compile org.jasypt jasypt-spring31 ${project.version} compile org.jasypt jasypt-spring4 ${project.version} compile org.jasypt jasypt-springsecurity2 ${project.version} compile org.jasypt jasypt-springsecurity3 ${project.version} compile org.jasypt jasypt-springsecurity4 ${project.version} compile org.jasypt jasypt-wicket13 ${project.version} compile org.jasypt jasypt-wicket15 ${project.version} compile jasypt-jasypt-1.9.3/jasypt-dist/src/000077500000000000000000000000001360667575700174365ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/artwork/000077500000000000000000000000001360667575700211275ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/artwork/jasypt-small.png000066400000000000000000000203121360667575700242530ustar00rootroot00000000000000PNG  IHDRRdԁsBIT|d pHYsV0ptEXtSoftwarewww.inkscape.org< IDATxwEoB!4S) ( xU.I‚ri . R"EI?|3{ |Orfgg}w"<:C=x Ri/H=M x<6x Ri/H=M x<6x Ri/H=M0Zx8M=J_5 v?=gBF/-;OVKxj_&x<-4!ԛF{?#i~--8y/'x0z׬ׁ~F/HK2 B5ڿ7[۪Jh!ti>-M⿷0ZkA-  =>kb4뮎 UQ+soJ^`a0pKcPTp4lǤI&~ZewTH&mw,@m;MƸسR%sZ?WsI{g+0c895Ϧ>v#i&7Ik.ݰТvkA94'6Qa2X6?< -=JOVgAd^- G}'\Ntum+HR>цuJ/2ynŀS]3D/ɰdí$XӇ+uHSyai?ۣM{5ߤ0h8܎ Fۚ 4ⷨ ҉:I< 8A% !4/y~#^F]\ RO)U?kk')ŵAc;\S$~u)b= -}o˥I|[Sh6Ϙߣq}IgEo4{AZ>j]j}_oeR5h{Ǡ"> QV!hsAm `AX.]cv2iQ›vH= V򩕧7QbTSYߤ:==7;-~Ee~\IA:UA:4iFSyA-f>N tMZ&pwcpe]5_NwIAZ;_F?ݡUg`hMi7J(Q ÀkMzt4:4 6<{ Dp}S^ R׏u6a|1+Aͣe@S^ ҢHRԺ8^'4{CRpbGV]T:u€.B(o0t)m[qzO%z%H!]F; apj<=H3lY{kt?dp} M.ktI2.װd6eXkJSNOlݛ"g̣q~A}>jkW+]!M;tkHPK4/1px"=z*ϥ}hQzу0ڟ*y>ܽq;L{*z 蓸\&qٴ~P,HaBFQ/y~jUipBF9Kc}3//TmKWcFI$.J*&PbFMq;[t}Z-amHg Z EKE![ 蛨3OAZ(W\Ax;Ep'.feϲY3>atXFfڭϵ(Rb8lѰ~6iu4UH|a%KF碕X4+sgޥ\K*idͧT 0Z- Zҭ.sn` iʂ>|t 62G4qH-U퓭⊴zwڽF;}U'dэ<8ȦJ&h2E0MWEA-&v$ hfcx]zdy]lBqAX(4hU4ME1 NBmd6տ;6.iǨQTkBvq [$v%7iDG6 v`C$n5bѪA l.{ew*s]"yKi[P>/M0-'{AQBualS//Ie`8x4uKd˝>T'iEX}U2~} 5Ժ~&}-+قa/0 ~ ThGyD`&}P -*[5 !AMBmOˠ;KL0 t+>y;4| Iؕm k 13,Mļ:BįagrQ$HFNACi~`vZ)|ׁ$MUr>+7 }eS+R=uQ{S(I L9f{Ihg0~ѿ$i,m\Tst74 E"A:xB< ЇВ2w0/y m$|]75nyCz!H]v(i [)5.4EC]@ f7i2p+DZ Am QSNd& ĚnB#2嗱Y@%$6AOy 4X*iѾhĕ{عOK#44/ h%,Q6~N$ۨq,js1Am.y>e\<Q96 ҷm4 i-^ ?EM1i4[&OmڬTO[:g@)#[Zhwe:=MwStO4\ zE -v!_@x] ~a4MOAo7;})f}?.kTXYfk4wY ލjͰ-T~ιQ*׺׾|&Mstn MK*LWDwVqOs/(uf څȨ ,u'IG|;7$n./`_]wc_A}^UIOnX:B3J \-d i ט \kxzO\ZzA &Mbj,EQgۂԥCg{:fQq;nz<%H'gto'[ }fx>TtM0GT5a1" n/gofDOxlrKsMGIr[2fQ<|(殽>z/sllhi7,%o5 ż9M[:0y F*"bo..^ofz㳐ZWDWFBzMGvhJТ ǷcNϵlI1f3MD SWIDAgYþgahDѕ=hruCDFJc̉sWDÊ ЀE&o9N@#ЮmtA=y@i`Omh=O>ba 73Ѷ} M3?$Ff 0Ɯa8 U.'6P*4z hiƘDd) h0 hm1GةƘyESw1JqGEAjS}]XPZyF}ג FgBoO? |IRS?ܒ 5/"DQcE1γ0pK70skƘEd p1%9ל{80+"O"{cmBD&w130`[c̅v? cfbYo=cE=xc̿l"1u?_c.q? ߈-Ƙrd9LDR9c"rp1fu9kC!hC1)cu"Z `#c,9c9EDB lm?Q(2Ƽd1aFD1Ƽf#"re+BZ &T[s&)rd=gƐߌ&S~u8_Mg͂4Y0EjiZWYXsGp]1Ӏmxfˊ epyp@ݱeq@>ܱ ~>c}Dd1&+l&DADhmCv]3]"WM1cn/'8(A;0zv>6g"ơJƘƘϩ0AMNMCPE#{Cn-Ѫ ͻ/mQ>|/-2W1iQ`2 1Ƙ7?eh8Eda"*0OZ&c7ܯDdcL;_ rS87P;.?(g o,,"'9cfcre {2_~sl!"-"?BMi)O,}+vBsCahpV"r,j&bgC1<c);݆$/㱂-SD -MVAi y&qj -܎;AH#vMNMV!5¨vI\ !"Am`{cfed>#"ˢZcsֲ,c粁jt)e4  ` Ԥ0ێZgIƘ[fq:fBb Z8T`\.m3-H ey8~c Ƙ7Qq֚Ɍ4j'-fˀݨ/;rԗj㙦ю2%-"KV"Y[1viO8:(lhޟlVJdDdidvVnUCf.1ODwGc˛c~ |)u<)6Xc<#,s#zq~'*̎Ƙ'{9-MKia^½&c.b3EC3@{byeYH0w+`>ޔgEEdqoGAƘ'Dd20BDFcsF_GD Ed4eVQoCOcEd,wv` a`| VE]v81Xsx 1RT ?O&* Z`H6E wn[8󶈄"2~VsYOQ[ƘPA|9u#"2#%"""Rړ3ǻ8'sLQƺWlHiejc3#}NҲ3Y4%"""RZ]eVƺ〇x1y$"2+%"""Rn9`͌!'e'#X,pZWh:""=S."""%m991c1-ؤKT`:""}Q."""%i{Kt))w2#cǁU#"/%"""RR-7gg'#X6`/׃i%"""RRUe[c{9ikttBDZA Q(YnKRQ q;pf N HGVnvED"|^M`a~/ӔDDDUb^lZoDDz12Ɠ3֭EU␡t\DZC HK~lzpGOS2ƒ3֭HJs i mqi!cÀX89䪛6˙!c,/ɳC∈d]_x\MsT=f%e[Bj\DZE H[sVFXFpW~<%cXuVt1֭ ۯ)9!m13ƒ2=8X7c{f'"24nqz#"2 cI6 orݙc E H{|غ^dDD䌱K:X|*«3nKDU-V%^Zy?Kyϔ rKPDHϘ1!=ޏr J)WDd`JEVK!xQh:cX.׆cKj {1s!S}lF*2p=p0+JLjQo㋈M HKLdU0ЄC)!^}esPVKۅUsvL!|)X'ՇšY) OWLbih2jo{੤|=)8oE1 j{,iu \Ì?ju^H59|gmuK>@?[y0Q%S3֭\psbj3f;ؼyЭ@$u ϧQƺ_?qEDiltcʤOX0'U ٳI9w$%u8cwrP<Yƺ,HՔ[Ճ`/ ocnBج+㪤Mϣ#$%'7|jQݓ}x ͵O riʂGOzKN{Ǎl*i[x<&W2 ] >:鑱˯#jyeI/&_8*3bTӎmd>hldX&xLI+1Q0>|XTy~T~V_Gnq`-"X<҃y,"w)y?w9`R݃&~^C*Xʷh69(cݫc?ox. ҝDAccH?w٣%V@3yn倵uZ 6~|XY{1ӴuO~B;E\c+ƺCHBjMObT^F—eI7qד*Dj_W'j{Dy MO 2X3~rƺ'R61s6ֽM-v X{¿?B:f#))max-0۫`d`+KNצ'2U'GيZCDfd'58WrG[@2W $fm9lL/ƺH+$w+/6^[YI*/m6ۦ'3թMؓ sHIN#KףbTᾶzE'Hm<^e|#lcݾZt>(9VꡈH͚Lhpa:A p.][SU[Ϫ^/ ̰c `P뀗 X Ҫszb pcc a=('%o m oy/=H ^AƤd}'๴HRAKu_du+IHs+MR]F6 %Om檸jeÅRLtU ~V#u~`g)UX4p<qd ~\us۶uWƺ-H^ KX-^Kac[4= cHhwđ^&I]_IHsB?t渖*3X?3xr>Tx1+96)qBMÞX8me/-jb& ! hwrikƺ62Ϫgȿ?cbƺVF{sV$_X̆4uM}GuMO@DGI,?|o:t3JThMоԀa~ bfbW7k;n^D=H&LFt6\xS* D~_Rwl_[ Lo 1HZ$M]DYMA %A5=ԧKImU꠳A}*'BYv$ʜO/i+XCb{^1ևV񡍁Mgc<׿3,ʻ\b2ppfgG붌`C$u 1֥o,Jj07 zmc>RMژO|Psq?o龃T,61)g-b[=Ky]MObG=pUcݣIEJK<$?@ܬbwDK-R-*YvSHGn{k Ԧ'!"t>UIںWYTGle"`1N}(S1[XC8&_t \{gД/A?)w~ze⭀bϨ>wQ~w'8Z[Ub*z" zR&H)H߳*.)_ UX"boq-cͤ3"T8 +WIXw̡"AF*5b%8fr9it]9{>%ăy_n/:`cv*ATي7%`&'ϙ~X*HmKKslY-G>kRq_g_z$ߦz"ҐڬT/=بW(v^Jz:>M[bU=udz i ocn{Qal??|a8>}tzhVhY]~ ev|0mNjUCӘ|XYmIXw=[N ' L5tȜAŅ^[(vg `:CR8(c2C Ťb?+rTΟ~)ƺ+EO1P z, Pcra5K Ĭ] j`r%)O[ uG:sAr~M㲢3cg/2ɩs:vt&Oo,Ο/uݚ1o[|> \{[ҎO,ѱduc3}x;a ~c~N_9fco$5nʾƺ[KY=s(qED$^Yf*%蕪ס[ #`l Z4f5=\riWc8XqRQ8^搶oR֪h]n[<էRn{3a'=X/UD7'%"2޿F+E ^lOP+۳1{2kdZz1j95=Ԗ͔/(?7;P6ǒa1de{f#σF6AxD#jmnxJE|8[X\ l7gt|09 m1֨130-)e\?=u%ٗ `[ALNb;vimRȶ8c"2g`_77ێ?c弙&]myx|Nb73|qI"ؿk`̞!oұ:m#V,zl6$5&~`}Ti}097dy~Z?-1+HIzSqrjm1AAxwWgfΨyV'+s<bF2A m5c1o>3A|Vf>3yuݺR}r2_Vܐ3 >l+^3@J@sȿ~8vV5Y_r6M QMsθjOW ^Mo'ͨrV${xms|bv}% 5w, |Cŝ5S?9H1J{7.m>@Ot ~jVd7.;5J/|@.'A?,*1 c0 "ܫ0 z 5ƺeHr tލ˪4]=|\Rl{Aӓh^I/pz12ֽ4AocjF3x~o[d>zUdwc4pv׹UIqyzvR IDAT4P9Uq_-:J ҃ly۵A~6Σ[)ўcjn)G6H'\^m^@Hu[Vχŗ#rn:cxmV*At+wA(~Tt _gm[015WڦD~e]j6u$]D:et`UcK۫1\yf9W۸ :.ƺ f='Ȃbg,8]3AI_QN7CaP{0`B{oqZAGIHIG&sXDdL(A_Kbdو2;.L:X6\ƐzͤM$kbƺ(ZAN(W:."RQh:̧=X'蕃ytSl۫9Hr7O~٠z>ԖaDdLn{j#X* #/u%*Y 盞pn 6:;x.G=~%C )A_ظlq HedtT nQ>E<,=Цunюu%XKbP(l ou% Ľ@̮S>K2EkC0cݦ3y obu3O MX' hCOkzRt}jQ{Z cmI[Sϥ?£3<o""PhY/Yc݊21|yT>nLӓg1S p ƺŁ'qI[Wu^x<]+sZlpGoϟOƺĘho7֭R0T |[|{^0tMdW+cݒ@B񴂾=vuMϥKMOb\N*ޅb/g^5dfrSؽR."2MdWwVEy LFA]x p{sXwpӓc%W4֭\0~Rs zMu ?8WŚvHgR{X!kLz1@[e%=[(2ԳAmenC}&}QӅԪ.k}a""Xh`a'2ǫ~b MXg[Y:(-`WQ6XΦ'1>FwU(^Wo+9!<2gOdކ2ye qEDj1 :eOY3<<ߖĨ 1mzS|Xsӓ7U ,B'Wt&+q$wF5As4%3(;b _3Y1/kz9wu5=1gS 4-_"nuؿ+1LJ?@Qϱ~xt(AYΠW3ߘ1I12ZAoP CMϣcMOd/[(r q%VЯj񎁦Lе."BJЧ77߆ޠڝg1V98ITo+QXf |Oզ2^;??UpWڱSP Oo"swd y=pBx`CR\n_kM cs,T'(q uo+@W?;/qAe]9NR."}zդ꺹/cQ`2;*߿MϥhcMOd|P-z] mv zmuK ?oP Hm:"͉ꐻµoyo^H{VN4֕l$!?X1{] mm8c^JЧT ND:Su[l12J[&)I}slfY)w=*zUNwg}&=+JEF!AW*c#3U b𷓶\*/$A G?/c^1_C^R tiB^ba[xyƐ?oT<X@ Ĕ>T9$}{cc{\\(ƺ{xK3 :iZ%c[ T "t6As"sJl*g]`1Yv7qw ܌ |Pŀ{x_/сj uxq@܁TUsu%"2B]x/=u-W%/o5֕*w ~n~Ϗ.C[PnIn(w%VA %5Q fNqzJ@ &vRL֤]ңa?E'T/dtګAscE!T/; 51[ ijR4.X69~Ϻb;uW~C_0ƺ$wgdOI%>ozyqq""PPbu*Z?֊υ8"K+{.uOb]iJЋ1=;.Z\kIEd(AЭnW8hUw:tYX {'kr5c] nz'SP-JГ^ :+PMt)J49^VƺG q cÁ c~TxϮqqSvV>2/ƺc )B}nxqПnq w)LЫ~ Z ԁuۉ2n.W2Zt }MCj{A1;HIz)4=X,W 949mJ=7qV=Y@hHdN1s*_Y(nPbw-KjVG%0DNxM';X+jӷsП~~Qw*WD1]MDZ@\Iƺu Ƃ=2=CmPaBbgRvvz?48\r+@ (e`1/9fN:."%(3R+Us V11?_aujc*goz}P̌uZ {cKJEd(AD9)A/X7 ݴ/kThmH^nz}RuK$cf[ iHܺ▪nE+ZAQ^X ? Oc>Я\ FcGsH' i63- ,Y(VwT ה=7%ՃN0-Amc^C_Kb4j'/cb_/R-@ :ƺ)҃|(^ z b?hp ];^eⶖ X 񇿳ޯ9}@gv 8?W^{k1Y&% zIs鸃 U^og͂JcUf[ b.w*_ H픠'bT2A1u4\ըE25o?3ޜ@>)ӈ8z@GUj1' i\D9LW- QX'ƺ/Π(?2[o,SfDO?X5?@R-s8{}&33/quu׵a[ٷ\WtF'3Ǽ6sQr.#*~u}_GMcT{P0= RE%&-cݎVuypg%2:3ۡ Zƺ5 oc뀽gy<1kN=n} pve_IbS"aJuw(~?ݻ|%q\`hn=^Xf$2ڔwfdc Xi[lvOnIͽeukg n=ziz,cezW =0K3 n ֥D+$ƺukvߍn_`۹DF^~PkE7/-qUђcڇbSebcN(Wzy cIJC?) %VЯ墔ƺ]= ث@: n3cH4 \j]+|j0yt)A :u+[`j;c+V4=XZUoKzȑHHݮnoB8h%V 7-^{NZ؆g[8x4DX`k9U5~Hn"X``rS~{nT-or+ ^"3֝@[vFX둱ncҙC lVBi%MuK-{`U-[𖕀/ƺ3܂LDF^V)}n׮ z,o=xt!SBP}پvG!}}ؔ&*8XwLu2 r@8;_K̮T}Tk mu>gz-իG^}9Rƺ0sr>i7crɗOn1EFVgjKpb7dYʕXKNZ!˽ͽ^J@PZN`S84qVN4ƺIhQc jqc@c]b^D,oxa ՜+7ֽ7W [?%LqjB=q6wmr<$y2jJ'ƺcް IDAT3ƃ8TcZ0u%d,yyڝ]㰛떪qLNQua[eۛ{B=sIy?%*OMc;gkV6O.vXyt> 8X7v Yf"C_-SFJЧa=I+ JCX뤿~Uu[|6QrVdTtZ.A/$N2@۲Ոa=&Rro˚\73Y *c݇HnF:nxEƞ% |ص@2Lgߏ?: ۡ2n ҶGU}1 n :u*9!ڃx_ 4cݶ"hr~t 5cq4OlUAD}@"JyCu{<欌u+#PҪ91V«l r퀖&Zf80JmC:G؅nos7!OU ]@mos<"sH}mU:Ay NIOiE;\oH4``'!6^mc^-sػbgYiջ, |Z|{ DU[>g']%Cʭ;<+zC+Jږ7k>ՅBVìu(S zvG NrQ kԑ,|X~wF:=_Ug0˱46= 6DN:{eK'иv7r,*f5;#:AJs 1r5B[&W(ss;ZkHr7ts> ҃kƺPI}݀b>OHm.sدNZY x a l1~Hz6떉DDڢ+ XooRѯa>bs^Cث LJsPc]+~>pޓoFRР;O~9ZA->0=XwiZ01_5M'uxAo}Z ̢5Er+]j6ᤊmXXxkzXIN/%%%I_k+NyK:O>ʱm}Z Pa}&9x] <8ػfd[S(h|g[L^hVƺ%b'UOͤHXGhevs۶]LMObю'}@bIÉ4U45:wp?| ~ߚƪsuPS0iPgFRA^h\>ƺՁ=2mؑr?/$u>9PI5`DqVz/w1ۛHb T-z@̺ $P6Rg_m,PӶƺ%u.0D?iZR' p!#RR-,6 붯>2-k{|.WQ&9TªDöa;mlkcݒIS^1XE,靖GCF)94>H߫_5T,1LG}&{jz"?Pv Nb?y\NB^↡-"nR6V;bpeWtNN%6s`g:wo`W/uZB=Gߪa,)HZmRgлRo/oz2]?XwYs|cV[5_PJJwiHE}Xx"Յ]+?XRQt5l۞LDn c>?zVa7,Wg1E:#MOGog{3KIHo.t %賈Tdg䜪Pk`Ƕ%yKRTM’qIKκ-(-Q(B~ ( b@8L CF2JNQ5ܚ{{y=]uLOw:uN U+'FӼywp8v3F%z/lXV]V.iwU+q/3 nˑfS\l-\==2͑l}^XV:!V3q 9t[Qh|\Hc`n+E7gU+3h브t[ pU+ևC~Kj;dBhz:{'[,vFZFrR̜òftx8Adj\297yQ, ]<ٿ7n+"#ŀg)Ojp p G /77rPV#[E .27jn+3Dqp .K˛դB#n+{k%81c) u%OioV)gy:pPZY]..Cl?݇Y<{}$8(SkuRkxY?xxXX7[̪7FWdwtgep΁_wI wc(׸HHB ^7п|dU+a.L'; m]`KժPd dAXXb]&Mo5'<@\%?QSVJ]%)wZeQ<f4ra.7̅%jr5Dq2rUgrB=k{c ]Fs ŁmDTLg  9+ qd'+ZNynPa"䫸Ex2ReQ, ̤}#kԪ'K)FQs*g,'-[/ЉdM,JO/k,Z2 H? 2T^&Ც. ,Ny"Q\fiìB=JTת9Q_Wk2%B 3~)]q 8aWDs̲; #Z27 RBP8/[~WP!D&jen~iEB/O ]!DqbhrJZ)}zB!Dz': !惸DEx NHd1 !Mz@WB9֪;IЉ: S!.B҈d7 *X}Ktƒ.]!lAVdB!(N?j/G !=BOQԗ*yυbE`JsvP!R%}u n!ғ:(+$hZt1=B!z^5Е N!DY,]ԥs!.bV~m49V<)}zyЅBW NtL!O)QFO:2ЅBW =O֪'J)do`6^VtJE!B!Dѫz%{B0Q,&U+>=L'91gתKRi!]!Q4У8y? .-jaң }!DsNZr}B8|X~s#N qB!J`yzDqr.D] 2U+ G!tG'U+8!!t;Z2wrF2 !=8`/ QWV.Q  w<.B!|>ϾZVlFQ| ^ z< VV^/AHfrd@B!J`p@:䓵j}Cl?%BQ L7 Q< L[c-`]`lI~عV$y#=xdB!ĨdQzGq2V\P{ jR4Bn+ vU+?m>[Vf,S!V,Xw,pn'u(N5-I!{|xw<#jn+'L&,lyB!Ĩe \Q[we jʜtBh 7>V\m%&b(N\!b1xam~J8Ch{rZbT&U+gu[>S B!F%1N8M;{n!%hij#CQ!F gDI< l_V."F'Gqrp0n (N6s !#3ud㒹 ,|جMYBQ$طVZv-`Oe_k0Xkgg>.D(;[B!`:1fmZ` sp*lk c΃887ykڏYk_k]bԾ tc66ƜdYۺZ1=ϬvY%1Ds1ccނ[lY`>0]AyƘi9pڿ=_?`YxK tQB`7}psuiZ{1f;`k_OYkmZB!B1~.k%dٴ2d79獸pG Ƙ́;ޑW_1On}[.B!:Ŧ %]HЇJ>!H̪%DT'sc Ƙ1˖ݯ@B!b`Zkg(;w30 0 g}j(N=cMӒ]хB!DK1c3M% KGlnJ'R{c8˟>Z~FB!bس˪ `0Ƭ@筵e.`{Zr賁'| c3ƌ)z@7ƌo)z}4+$qc1llfcVOt}~3am ?Ƙ[.B!30h]0HYXcrBG[kO)p5SpFW n Dp?}v^cI+ŀyƘw?ID`ukm%`?WrXr\V0ûpYw%p ž?l[c2,< LZ; <qfE>KymV%==b)΀k8~01ݛ+֎ۗuem"zXUk8 mk3v>JƘ܅귩F*******=^pT]9m}ZozW}m/ R%}>0#GUew~Ρ,wp%0K^UoBupナY ߉{f^7K3\V`&rJkr,;^yTQQQQQQ\::?)mxg[ 8:%?;s8)'k P ۸6KiZ6tp)= =sܺڙ2Z_~Έ! 3*fa+⌖ 7d`^lq5wxpȻfA]p,@أ63qWroyyGmGv%@,Rh̏xo68> q6tL-Z?vyb?KkAz|7{, l_w;XqK"A' 79 )= +n)y8e|N=C&2/tX\}+} doELsl@qa^OfӃpysYxpNR|bJ ,<(U/: (A_'{nrïz{ܻ໸A_u2#|Eq&$^K#g^ׂ [M\) 6N8H:3ؾv%@}~:p!UuAj)6/ BդW󀥛\q:Xgd1܇۸7Ȓܩ{R]϶w//}pAݷ 8O=%-x|7Ui|wuܳwO3}qs2|4cN0G**"?.h;103xg:u>.jjkg+;dQQQQQQQ~_RM%6NqɀAxO΂zz'6sqI-C}ei }XESnsoFF4Du +Xt3>Sv E ,u ^#{.A)[55\v[ #搓G զ߬>jԿ:{Sk^Q ޷GɐS/ }luw rF6C ~l\^gt_Jx``RQJp`5o:5CX.=3Sj~9n*l೛QQoI2kB!D.`Ƙq^8oQ، ƘI},q:-,&g=kY*i@}/dswH?gun 'Odԙ3KVgq\NbpwK.)%>goj` gђp4o kCx>lFF}p=}mȪ.? 巵\$FBܭkݪ1f@o[kʩ.ڣɩks{s1y:Yk_q9"K퇛bs֬g޷[n "Kɚ'Ƙp`Tp:cga Y8|~ٰGԹYlUU LK,3c~Jv7;.~-^7PqsнeքB$4jV/_k{[Gف%nV4qs#gs dB.kƘG1Q~Ucv>_)}o9׋8mjKlЌ10`\h^RH6&4Y7~kp4h[^ ր7Z3mRv9h-NwXkSo{\ⱺ[k#'8kZ3V Y3d}ӊ p,zknKqZT uX4nߪ>(6B^\ҵyB-wfi6+ǿ0lh![E;gpnu}T'k0=((~<˿>˾w q|A3Ru' p{ϥʃ.B;9(׃nLLy*xgoh%]}ƺ1&- pVkگ2stj3jYӆ]ˈRjj'pR=XheyXC/#m^5g ukuʀsa1fqca]}ϰ1~i5Lqj#+/WXkgt# O =Dxԙ{m.v|.d$8,FQ\kϭH}<)v >*. [)R{yAΦ_B׸%u'|*O`vV/۫{c?)=K t!X uH(sBxW}ONesuw9CG qYk_/nGc/1fق2c -vTC Z7c 9wM?fkiglzTNj像E;8 !#,u8s2Ys;>\c̺*<< yڅ tc4v@꽀R3|IӰOc[hLNT$yh}idYưgT ;se{~A g[L=W[kqny:l%*Z{U94F#_]׎}`SSh+gF „v[cv7ƌM}j"Zfpl5GSP@}гf{uJ3}Tޖ.BBF3/]ر{?C:֦ 5yY&} yl[ΰ~~X8Yr4azs @_;_k*NhOkàv;VPn9ֹ#\@`hPc`{H7v ~:|WM(NM+B#[I7Ч91f"\?ͩ:Tzgy~;jovObm5-4.BB=(Cc`C3%^f;ǩa5/kg1Xq~z93\Q^fn'ܸmȯz1߱]VN7n9:ӆG3n߷;׾Ⱥdp t 4&Ug Lp:9|Rj9p{N >Z9$Ƙi\Nٳ<-?1Rn<EZFo@B!gl/Dy!19zXkgYkT;`\>~,Ug cNt?oɪ=a6Yڄ:45|0T}0^2L֭9BCf{I ~+þp& ,Qc3ڟ`Y*/14#;uC6iql@nki2;39>Ԣ7rsni?Z |_k޳cV1@p2 t!q;-Ƙ]Nq3nח 1ȹzϭuߟ qKՙS/x4ƬgiNVc&o1` tcv~wppu tc̗p}:rA1c~sp 5k<ƘŌ1sWM,2kc6-Gdβ@B:W%Ȭij]chBQ8e`eB| Υ[ߞhxZyS,N>:!{ r#a1?1ƼQWaU臃0yM^Eg 1cΔ.Biu^I; cĭ},4c&8#w x>q-Y&ȬwTgy᭡a7*7 =7EKk/uI\4cŅ_֤I88怇7ONL/1°7֍+\1Qī/s,7#dZj$h%ƘM1~cL1&:Fq:13wm&YeZjcLdbY>Vn)6%ߜ"` 4 ¾צc3ƜAXk絒= gӄ3ͼ>i-DvN@ic.y76Gt0y).}cZLD IDAT XkJi}yIzx X5{q޳Sm3jr޿?_7x.OyfJTMA,~,nNp~Sg/rMJYH]ӢR8=.A[ܣz/3 f 87xVAs LPqN}[JtX5pYǥݝu  ~g?!hsM>{v; yY7h877)2f7}] 3 [#{Q`\s; [=+{}z{~B {18 Gmn|2o6ټoql9^YV*******+f'I4J(yH>, 0 6,c]>ss 9WM%;p'rcLIɽ9c[a21GXu>&:7U>)L\G fTc2}}f@IXor?uY@3 ENss83Pb_^r^rN{-ݹM~㓆t<.< ~3^Dž`#}!uUA]CQeϸ p2s{@e^KOw0p}:tNϪnx .Z&wr~[<,7=]J]ݙAfZk)PQQQQQQ\ESr:NBF ˘6fZQ8?<= :  VҤ9u[_,fyyS4 84d`?Ok8O] n!Z!9 v?to3=hO?(;i6le-3<;wes\ {cFRg}(lK,.RV,gF%umBMqY ڗۑ\ڬym ڝY{B!D⾓ BZ}#gYk 1;OGOG7R@B!z?ƘÃwOD,!1fp7.aSƘ#Ƙe1G U_7~LEqd !ɝƘ}z&D& |1f?`]'vU3!`Q<1WⲒ[}`kEpjNj+ABћƘ+uQ/!3 rwCA4n_Wy5^\ⷐqKf[S< aFˬ !=1LM}|;sѵ1~[>%Ucv.ąκB 7Ƙm3{Hk 2O vP.B Ƙ5]ULƘ/G91ؠ6dػ1f `n"D;c6=g;k =Æw %.r}֐%( cIENDB`jasypt-jasypt-1.9.3/jasypt-dist/src/artwork/jasypt.svg000066400000000000000000000064031360667575700231650ustar00rootroot00000000000000 image/svg+xml jasypt. JAVA·SIMPLIFIED·ENCRYPTION jasypt-jasypt-1.9.3/jasypt-dist/src/assembly/000077500000000000000000000000001360667575700212555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/assembly/dist.xml000066400000000000000000000302771360667575700227530ustar00rootroot00000000000000 dist zip ${basedir}/src/main/bin/ /bin *.sh *.bat ${basedir}/../jasypt/target/checkout/jasypt/target/apidocs/ /apidocs/jasypt/ **/* ${basedir}/../jasypt-acegisecurity/target/checkout/jasypt-acegisecurity/target/apidocs/ /apidocs/jasypt-acegisecurity/ **/* ${basedir}/../jasypt-hibernate3/target/checkout/jasypt-hibernate3/target/apidocs/ /apidocs/jasypt-hibernate3/ **/* ${basedir}/../jasypt-hibernate4/target/checkout/jasypt-hibernate4/target/apidocs/ /apidocs/jasypt-hibernate4/ **/* ${basedir}/../jasypt-hibernate5/target/checkout/jasypt-hibernate5/target/apidocs/ /apidocs/jasypt-hibernate5/ **/* ${basedir}/../jasypt-spring2/target/checkout/jasypt-spring2/target/apidocs/ /apidocs/jasypt-spring2/ **/* ${basedir}/../jasypt-spring3/target/checkout/jasypt-spring3/target/apidocs/ /apidocs/jasypt-spring3/ **/* ${basedir}/../jasypt-spring31/target/checkout/jasypt-spring31/target/apidocs/ /apidocs/jasypt-spring31/ **/* ${basedir}/../jasypt-spring4/target/checkout/jasypt-spring4/target/apidocs/ /apidocs/jasypt-spring4/ **/* ${basedir}/../jasypt-springsecurity2/target/checkout/jasypt-springsecurity2/target/apidocs/ /apidocs/jasypt-springsecurity2/ **/* ${basedir}/../jasypt-springsecurity3/target/checkout/jasypt-springsecurity3/target/apidocs/ /apidocs/jasypt-springsecurity3/ **/* ${basedir}/../jasypt-springsecurity4/target/checkout/jasypt-springsecurity4/target/apidocs/ /apidocs/jasypt-springsecurity4/ **/* ${basedir}/../jasypt-wicket13/target/checkout/jasypt-wicket13/target/apidocs/ /apidocs/jasypt-wicket13/ **/* ${basedir}/../jasypt-wicket15/target/checkout/jasypt-wicket15/target/apidocs/ /apidocs/jasypt-wicket15/ **/* ${basedir}/../jasypt/target/checkout/jasypt/target/ /lib jasypt-${project.version}.jar jasypt-${project.version}-lite.jar jasypt-${project.version}-javadoc.jar jasypt-${project.version}-sources.jar ${basedir}/../jasypt-acegisecurity/target/checkout/jasypt-acegisecurity/target/ /lib jasypt-acegisecurity-${project.version}.jar jasypt-acegisecurity-${project.version}-javadoc.jar jasypt-acegisecurity-${project.version}-sources.jar ${basedir}/../jasypt-hibernate3/target/checkout/jasypt-hibernate3/target/ /lib jasypt-hibernate3-${project.version}.jar jasypt-hibernate3-${project.version}-javadoc.jar jasypt-hibernate3-${project.version}-sources.jar ${basedir}/../jasypt-hibernate4/target/checkout/jasypt-hibernate4/target/ /lib jasypt-hibernate4-${project.version}.jar jasypt-hibernate4-${project.version}-javadoc.jar jasypt-hibernate4-${project.version}-sources.jar ${basedir}/../jasypt-hibernate5/target/checkout/jasypt-hibernate5/target/ /lib jasypt-hibernate5-${project.version}.jar jasypt-hibernate5-${project.version}-javadoc.jar jasypt-hibernate5-${project.version}-sources.jar ${basedir}/../jasypt-spring2/target/checkout/jasypt-spring2/target/ /lib jasypt-spring2-${project.version}.jar jasypt-spring2-${project.version}-javadoc.jar jasypt-spring2-${project.version}-sources.jar ${basedir}/../jasypt-spring3/target/checkout/jasypt-spring3/target/ /lib jasypt-spring3-${project.version}.jar jasypt-spring3-${project.version}-javadoc.jar jasypt-spring3-${project.version}-sources.jar ${basedir}/../jasypt-spring31/target/checkout/jasypt-spring31/target/ /lib jasypt-spring31-${project.version}.jar jasypt-spring31-${project.version}-javadoc.jar jasypt-spring31-${project.version}-sources.jar ${basedir}/../jasypt-spring4/target/checkout/jasypt-spring4/target/ /lib jasypt-spring4-${project.version}.jar jasypt-spring4-${project.version}-javadoc.jar jasypt-spring4-${project.version}-sources.jar ${basedir}/../jasypt-springsecurity2/target/checkout/jasypt-springsecurity2/target/ /lib jasypt-springsecurity2-${project.version}.jar jasypt-springsecurity2-${project.version}-javadoc.jar jasypt-springsecurity2-${project.version}-sources.jar ${basedir}/../jasypt-springsecurity3/target/checkout/jasypt-springsecurity3/target/ /lib jasypt-springsecurity3-${project.version}.jar jasypt-springsecurity3-${project.version}-javadoc.jar jasypt-springsecurity3-${project.version}-sources.jar ${basedir}/../jasypt-springsecurity4/target/checkout/jasypt-springsecurity4/target/ /lib jasypt-springsecurity4-${project.version}.jar jasypt-springsecurity4-${project.version}-javadoc.jar jasypt-springsecurity4-${project.version}-sources.jar ${basedir}/../jasypt-wicket13/target/checkout/jasypt-wicket13/target/ /lib jasypt-wicket13-${project.version}.jar jasypt-wicket13-${project.version}-javadoc.jar jasypt-wicket13-${project.version}-sources.jar ${basedir}/../jasypt-wicket15/target/checkout/jasypt-wicket15/target/ /lib jasypt-wicket15-${project.version}.jar jasypt-wicket15-${project.version}-javadoc.jar jasypt-wicket15-${project.version}-sources.jar ${basedir}/ / LICENSE.txt README.txt NOTICE.txt ChangeLog.txt ${settings.localRepository}/com/ibm/icu/icu4j/3.4.4 /lib icu4j-3.4.4.jar ${basedir}/ / LICENSE.txt README.txt NOTICE.txt /lib false runtime org.jasypt:jasypt org.jasypt:jasypt-dist org.jasypt:jasypt-acegisecurity org.jasypt:jasypt-hibernate3 org.jasypt:jasypt-hibernate4 org.jasypt:jasypt-hibernate5 org.jasypt:jasypt-spring2 org.jasypt:jasypt-spring3 org.jasypt:jasypt-spring31 org.jasypt:jasypt-spring4 org.jasypt:jasypt-springsecurity2 org.jasypt:jasypt-springsecurity3 org.jasypt:jasypt-springsecurity4 org.jasypt:jasypt-wicket13 org.jasypt:jasypt-wicket15 jasypt-jasypt-1.9.3/jasypt-dist/src/main/000077500000000000000000000000001360667575700203625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/000077500000000000000000000000001360667575700211325ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/decrypt.bat000066400000000000000000000012271360667575700232760ustar00rootroot00000000000000@ECHO OFF set SCRIPT_NAME=decrypt.bat set EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI set EXEC_CLASSPATH=. if "%JASYPT_CLASSPATH%" == "" goto computeclasspath set EXEC_CLASSPATH=%EXEC_CLASSPATH%;%JASYPT_CLASSPATH% :computeclasspath IF "%OS%" == "Windows_NT" setlocal ENABLEDELAYEDEXPANSION FOR %%c in (%~dp0..\lib\*.jar) DO set EXEC_CLASSPATH=!EXEC_CLASSPATH!;%%c IF "%OS%" == "Windows_NT" setlocal DISABLEDELAYEDEXPANSION set JAVA_EXECUTABLE=java if "%JAVA_HOME%" == "" goto execute set JAVA_EXECUTABLE="%JAVA_HOME%\bin\java" :execute %JAVA_EXECUTABLE% -classpath %EXEC_CLASSPATH% %EXECUTABLE_CLASS% %SCRIPT_NAME% %* jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/decrypt.sh000066400000000000000000000013141360667575700231370ustar00rootroot00000000000000#!/bin/sh SCRIPT_NAME=decrypt.sh EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI BIN_DIR=`dirname $0` DIST_DIR=$BIN_DIR/.. LIB_DIR=$DIST_DIR/lib EXEC_CLASSPATH="." if [ -n "$JASYPT_CLASSPATH" ] then EXEC_CLASSPATH=$EXEC_CLASSPATH:$JASYPT_CLASSPATH fi for a in `find $LIB_DIR -name '*.jar'` do EXEC_CLASSPATH=$EXEC_CLASSPATH:$a done JAVA_EXECUTABLE=java if [ -n "$JAVA_HOME" ] then JAVA_EXECUTABLE=$JAVA_HOME/bin/java fi if [ "$OSTYPE" = "cygwin" ] then EXEC_CLASSPATH=`echo $EXEC_CLASSPATH | sed 's/:/;/g' | sed 's/\/cygdrive\/\([a-z]\)/\1:/g'` JAVA_EXECUTABLE=`cygpath --unix "$JAVA_EXECUTABLE"` fi "$JAVA_EXECUTABLE" -classpath $EXEC_CLASSPATH $EXECUTABLE_CLASS $SCRIPT_NAME "$@" jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/digest.bat000066400000000000000000000012171360667575700231020ustar00rootroot00000000000000@ECHO OFF set SCRIPT_NAME=digest.bat set EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptStringDigestCLI set EXEC_CLASSPATH=. if "%JASYPT_CLASSPATH%" == "" goto computeclasspath set EXEC_CLASSPATH=%EXEC_CLASSPATH%;%JASYPT_CLASSPATH% :computeclasspath IF "%OS%" == "Windows_NT" setlocal ENABLEDELAYEDEXPANSION FOR %%c in (%~dp0..\lib\*.jar) DO set EXEC_CLASSPATH=!EXEC_CLASSPATH!;%%c IF "%OS%" == "Windows_NT" setlocal DISABLEDELAYEDEXPANSION set JAVA_EXECUTABLE=java if "%JAVA_HOME%" == "" goto execute set JAVA_EXECUTABLE="%JAVA_HOME%\bin\java" :execute %JAVA_EXECUTABLE% -classpath %EXEC_CLASSPATH% %EXECUTABLE_CLASS% %SCRIPT_NAME% %* jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/digest.sh000066400000000000000000000013041360667575700227430ustar00rootroot00000000000000#!/bin/sh SCRIPT_NAME=digest.sh EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptStringDigestCLI BIN_DIR=`dirname $0` DIST_DIR=$BIN_DIR/.. LIB_DIR=$DIST_DIR/lib EXEC_CLASSPATH="." if [ -n "$JASYPT_CLASSPATH" ] then EXEC_CLASSPATH=$EXEC_CLASSPATH:$JASYPT_CLASSPATH fi for a in `find $LIB_DIR -name '*.jar'` do EXEC_CLASSPATH=$EXEC_CLASSPATH:$a done JAVA_EXECUTABLE=java if [ -n "$JAVA_HOME" ] then JAVA_EXECUTABLE=$JAVA_HOME/bin/java fi if [ "$OSTYPE" = "cygwin" ] then EXEC_CLASSPATH=`echo $EXEC_CLASSPATH | sed 's/:/;/g' | sed 's/\/cygdrive\/\([a-z]\)/\1:/g'` JAVA_EXECUTABLE=`cygpath --unix "$JAVA_EXECUTABLE"` fi "$JAVA_EXECUTABLE" -classpath $EXEC_CLASSPATH $EXECUTABLE_CLASS $SCRIPT_NAME "$@" jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/encrypt.bat000066400000000000000000000012271360667575700233100ustar00rootroot00000000000000@ECHO OFF set SCRIPT_NAME=encrypt.bat set EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI set EXEC_CLASSPATH=. if "%JASYPT_CLASSPATH%" == "" goto computeclasspath set EXEC_CLASSPATH=%EXEC_CLASSPATH%;%JASYPT_CLASSPATH% :computeclasspath IF "%OS%" == "Windows_NT" setlocal ENABLEDELAYEDEXPANSION FOR %%c in (%~dp0..\lib\*.jar) DO set EXEC_CLASSPATH=!EXEC_CLASSPATH!;%%c IF "%OS%" == "Windows_NT" setlocal DISABLEDELAYEDEXPANSION set JAVA_EXECUTABLE=java if "%JAVA_HOME%" == "" goto execute set JAVA_EXECUTABLE="%JAVA_HOME%\bin\java" :execute %JAVA_EXECUTABLE% -classpath %EXEC_CLASSPATH% %EXECUTABLE_CLASS% %SCRIPT_NAME% %* jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/encrypt.sh000066400000000000000000000013141360667575700231510ustar00rootroot00000000000000#!/bin/sh SCRIPT_NAME=encrypt.sh EXECUTABLE_CLASS=org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI BIN_DIR=`dirname $0` DIST_DIR=$BIN_DIR/.. LIB_DIR=$DIST_DIR/lib EXEC_CLASSPATH="." if [ -n "$JASYPT_CLASSPATH" ] then EXEC_CLASSPATH=$EXEC_CLASSPATH:$JASYPT_CLASSPATH fi for a in `find $LIB_DIR -name '*.jar'` do EXEC_CLASSPATH=$EXEC_CLASSPATH:$a done JAVA_EXECUTABLE=java if [ -n "$JAVA_HOME" ] then JAVA_EXECUTABLE=$JAVA_HOME/bin/java fi if [ "$OSTYPE" = "cygwin" ] then EXEC_CLASSPATH=`echo $EXEC_CLASSPATH | sed 's/:/;/g' | sed 's/\/cygdrive\/\([a-z]\)/\1:/g'` JAVA_EXECUTABLE=`cygpath --unix "$JAVA_EXECUTABLE"` fi "$JAVA_EXECUTABLE" -classpath $EXEC_CLASSPATH $EXECUTABLE_CLASS $SCRIPT_NAME "$@" jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/listAlgorithms.bat000066400000000000000000000012261360667575700246300ustar00rootroot00000000000000@ECHO OFF set SCRIPT_NAME=listAlgorithms.bat set EXECUTABLE_CLASS=org.jasypt.intf.cli.AlgorithmRegistryCLI set EXEC_CLASSPATH=. if "%JASYPT_CLASSPATH%" == "" goto computeclasspath set EXEC_CLASSPATH=%EXEC_CLASSPATH%;%JASYPT_CLASSPATH% :computeclasspath IF "%OS%" == "Windows_NT" setlocal ENABLEDELAYEDEXPANSION FOR %%c in (%~dp0..\lib\*.jar) DO set EXEC_CLASSPATH=!EXEC_CLASSPATH!;%%c IF "%OS%" == "Windows_NT" setlocal DISABLEDELAYEDEXPANSION set JAVA_EXECUTABLE=java if "%JAVA_HOME%" == "" goto execute set JAVA_EXECUTABLE="%JAVA_HOME%\bin\java" :execute %JAVA_EXECUTABLE% -classpath %EXEC_CLASSPATH% %EXECUTABLE_CLASS% %SCRIPT_NAME% %* jasypt-jasypt-1.9.3/jasypt-dist/src/main/bin/listAlgorithms.sh000066400000000000000000000013131360667575700244710ustar00rootroot00000000000000#!/bin/sh SCRIPT_NAME=listAlgorithms.sh EXECUTABLE_CLASS=org.jasypt.intf.cli.AlgorithmRegistryCLI BIN_DIR=`dirname $0` DIST_DIR=$BIN_DIR/.. LIB_DIR=$DIST_DIR/lib EXEC_CLASSPATH="." if [ -n "$JASYPT_CLASSPATH" ] then EXEC_CLASSPATH=$EXEC_CLASSPATH:$JASYPT_CLASSPATH fi for a in `find $LIB_DIR -name '*.jar'` do EXEC_CLASSPATH=$EXEC_CLASSPATH:$a done JAVA_EXECUTABLE=java if [ -n "$JAVA_HOME" ] then JAVA_EXECUTABLE=$JAVA_HOME/bin/java fi if [ "$OSTYPE" = "cygwin" ] then EXEC_CLASSPATH=`echo $EXEC_CLASSPATH | sed 's/:/;/g' | sed 's/\/cygdrive\/\([a-z]\)/\1:/g'` JAVA_EXECUTABLE=`cygpath --unix "$JAVA_EXECUTABLE"` fi "$JAVA_EXECUTABLE" -classpath $EXEC_CLASSPATH $EXECUTABLE_CLASS $SCRIPT_NAME "$@" jasypt-jasypt-1.9.3/jasypt-dist/src/site/000077500000000000000000000000001360667575700204025ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/000077500000000000000000000000001360667575700211665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/advancedconfiguration.apt000066400000000000000000000071221360667575700262330ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Advanced Configuration ------- Advanced configuration for encryptors and digesters Jasypt allows its provided encryptors and digesters to be configured in any specific ways the user may need. This is achieved by letting the user define his/her own classes, implementing specific interfaces, and putting these objects in charge of retrieving the configuration parameters in the user's preferred way. The <*Config> interfaces which have to be implemented are: * <> for the configuration of <<>> and <<>> objects (by calling their respective <<>> methods). There also is an <> interface for adding configuration parameters specific to String digesting. [] * <> for the configuration of <<>>, <<>>, <<>> and <<>> objects (also by calling their respective <<>> methods). There also is an <> interface for adding configuration parameters specific to String encryption. Jasypt provides at the moment two of the <*Config> interfaces for digesters, and three for encryptors: * <> and <>, which allow setting configuration properties in a (via <<>> methods). Their variants are <> and <>. [] * <> and <>, which besides allowing <<>> configuration, also allow the values of the configuration properties to be set in environment variables or JVM system properties. This will allow the user, for example, to set an encryption password in an environment variable, start the application or application server, let the jasypt encryptor object initialise, and then unset the variable (thus hiding it). Their variants are <> and <>. [] * <> (and <>), only for Password Based Encryption, which allow the configuration of encryptor passwords in web applications from the web itself, once the webapp has been deployed (and thus allowing developers not to store the encryption passwords in any file, simply providing it to the app each time it is deployed). {{{./webconfiguration.html}Learn more}}. <>: If a *Config object returns <<>> for a configuration value, then it will be simply ignored, and other configuration mechanisms (like default values or the encryptor's or digester's own <<>> methods) will be honored. . jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/bouncy-castle.apt000066400000000000000000000064241360667575700244520ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Using Jasypt with the Bouncy Castle JCE provider ------- Using Jasypt with the Bouncy Castle JCE provider The {{{http://www.bouncycastle.org}Bouncy Castle}} is a powerful and complete cryptography package which includes, among other things, a JCE provider implementing much more encryption and digest algorithms than the standard Java Virtual Machine's provider. Among others, Bouncy Castle implements the {{{http://en.wikipedia.org/wiki/Advanced_Encryption_Standard}AES (Advanced Encryption Standard) [wikipedia]}} algorithms. Bouncy Castle can be used in jasypt in a very easy way, just like with any other JCE provider. For this, we should know: * The provider class (implementation of <<>>) is <> [] * The name of the Bouncy Castle provider, once registered, is "<>". Now we can use Bouncy Castle at jasypt both registering the provider beforehand (thus using its name, <<>>) or not registering it (and using its provider class): ---------------- ... StandardPBEStringEncryptor myFirstEncryptor = new StandardPBEStringEncryptor(); myFirstEncryptor.setProvider(new BouncyCastleProvider()); myFirstEncryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); myFirstEncryptor.setPassword(myPassword); String myFirstEncryptedText = myFirstEncryptor.encrypt(myText); ... ---------------- ...or, by provider name... ---------------- ... Security.addProvider(new BouncyCastleProvider()); ... StandardPBEStringEncryptor mySecondEncryptor = new StandardPBEStringEncryptor(); mySecondEncryptor.setProviderName("BC"); mySecondEncryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); mySecondEncryptor.setPassword(myPassword); String mySecondEncryptedText = mySecondEncryptor.encrypt(myText); ... ---------------- We can also use it for digests... ---------------- ... StandardStringDigester digester = new StandardStringDigester(); digester.setProvider(new BouncyCastleProvider()); digester.setAlgorithm("WHIRLPOOL"); String digest = digester.digest(message); ... ---------------- ...we can also use password-specific utils like ConfigurablePasswordEncryptor... ---------------- ... ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor(); passwordEncryptor.setProvider(new BouncyCastleProvider()); passwordEncryptor.setAlgorithm("WHIRLPOOL"); String encryptedPassword = passwordEncryptor.encryptPassword(password); ... ---------------- And also, we can use it in Hibernate mappings, when configuring the typedefs by extension, like: ------------------- ... PBEWITHSHA256AND128BITAES-CBC-BC BC jasypt 1000 ... ... ... ... ------------------- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/cli.apt000066400000000000000000000176721360667575700224600ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting from the command line ------- Encrypting from the command line: Jasypt CLI Tools Jasypt supplies a bunch of Command Line Interface (CLI) tools, useful for performing encryption, decryption and digest operations from the command line. In order to use this tools, you should {{{./download.html}download}} the zip file (named <<>>) and unzip it. Once done, you will find a <<>> directory containing: * A set of <<.bat>> files for Windows execution: * <<>>: for PBE (Password Based Encryption) encryption operations. * <<>>: for PBE (Password Based Encryption) decryption operations. * <<>>: for message digest operations. * <<>>: for listing the digest and PBE encryption algorithms available in your JVM. [] * A set of <<.sh>> files for Linux/UNIX execution: * <<>>: for PBE (Password Based Encryption) encryption operations. * <<>>: for PBE (Password Based Encryption) decryption operations. * <<>>: for message digest operations. * <<>>: for listing the digest and PBE encryption algorithms available in your JVM. <(Please note that before using the .sh files, you might need to add execution permissions to them with something like "chmod u+x *.sh".)> [] Most of these commands are executed with the following syntax: --- [command] [argument1]=[value1] [argument2]=[value2] ... --- For example: --- ./digest.sh input="U3ERPA33_W0RD" algorithm=SHA1 --- <>: All these commands honor the existence of a <<>> environment variable containing extended classpath definitions for the execution of the encryption/decryption/digest commands. This feature can be useful if the user wants to configurehis/her own security provider or salt generator implementation, or if the user is using Java 1.5 or older and needs to add icu4j's jars to the classpath (which are not included with jasypt's distribucion any more). <>: Most of these commands admit a <<>> parameter (which can be set to (default) or ) which let the user switch from an explanatory output to a very reduced one, showing only the result of the operation (specially useful for scripting). * Encryption from the command line ("encrypt" command) Encryption is performed at the command line with the <<>>/<<>> command, and its usage and parametrization corresponds exactly with that of a <<>>. All the default values of this encryptor class are assumed when executing the CLI command. To know more, see {{{./javadoc.html}JavaDoc}}. <>: --- $ ./encrypt.sh Using classpath: .:./lib/icu4j-3.4.4.jar:./lib/jasypt-1.9.x.jar USAGE: encrypt.sh [ARGUMENTS] * Arguments must apply to format: "arg1=value1 arg2=value2 arg3=value3 ..." * Required arguments: input password * Optional arguments: verbose algorithm keyObtentionIterations saltGeneratorClassName providerName providerClassName stringOutputType ivGeneratorClassName --- <>: --- $ ./encrypt.sh input="This is my message to be encrypted" password=MYPAS_WORD ----ENVIRONMENT----------------- Runtime: Sun Microsystems Inc. Java HotSpot(TM) Client VM 1.6.0_03-b05 ----ARGUMENTS------------------- input: This is my message to be encrypted password: MYPAS_WORD ----OUTPUT---------------------- k1AwOd5XuW4VfPQtEXEdVlMnaNn19hivMbn1G4JQgq/jArjtKqryXksYX4Hl6A0e --- --- $ ./encrypt.sh input="This is my message to be encrypted" password=MYPAS_WORD verbose=false uv9+BnQFuZbfTV5Kf45oBOr0eJzBW5AS+XaYY+Lu5XWYhGgl0Ee41P0QUGpIrfyD --- * Decryption from the command line ("decrypt" command) Decryption is performed at the command line with the <<>>/<<>> command, and its usage and parametrization corresponds exactly with that of a <<>>. All the default values of this encryptor class are assumed when executing the CLI command. To know more, see {{{./javadoc.html}JavaDoc}}. <>: --- $ ./decrypt.sh Using classpath: .:./lib/icu4j-3.4.4.jar:./lib/jasypt-1.9.x.jar USAGE: decrypt.sh [ARGUMENTS] * Arguments must apply to format: "arg1=value1 arg2=value2 arg3=value3 ..." * Required arguments: input password * Optional arguments: verbose algorithm keyObtentionIterations saltGeneratorClassName providerName providerClassName stringOutputType ivGeneratorClassName --- <>: --- $ ./decrypt.sh input="k1AwOd5XuW4VfPQtEXEdVlMnaNn19hivMbn1G4JQgq/jArjtKqryXksYX4Hl6A0e" password=MYPAS_WORD ----ENVIRONMENT----------------- Runtime: Sun Microsystems Inc. Java HotSpot(TM) Client VM 1.6.0_03-b05 ----ARGUMENTS------------------- input: k1AwOd5XuW4VfPQtEXEdVlMnaNn19hivMbn1G4JQgq/jArjtKqryXksYX4Hl6A0e password: MYPAS_WORD ----OUTPUT---------------------- This is my message to be encrypted --- --- $ ./decrypt.sh input="k1AwOd5XuW4VfPQtEXEdVlMnaNn19hivMbn1G4JQgq/jArjtKqryXksYX4Hl6A0e" password=MYPAS_WORD verbose=false This is my message to be encrypted --- * Digest from the command line ("digest" command) Digest is performed at the command line with the <<>>/<<>> command, and its usage and parametrization corresponds exactly with that of a <<>>. All the default values of this digester class are assumed when executing the CLI command. To know more, see {{{./javadoc.html}JavaDoc}}. <>: --- $ ./digest.sh Using classpath: .:./lib/icu4j-3.4.4.jar:./lib/jasypt-1.9.x.jar USAGE: digest.sh [ARGUMENTS] * Arguments must apply to format: "arg1=value1 arg2=value2 arg3=value3 ..." * Required arguments: input * Optional arguments: verbose algorithm iterations saltSizeBytes saltGeneratorClassName providerName providerClassName invertPositionOfSaltInMessageBeforeDigesting invertPositionOfPlainSaltInEncryptionResults useLenientSaltSizeCheck unicodeNormalizationIgnored stringOutputType prefix suffix --- <>: --- $ ./digest.sh input="userDaTaBaSe_pass_word" ----ENVIRONMENT----------------- Runtime: Sun Microsystems Inc. Java HotSpot(TM) Client VM 1.6.0_03-b05 ----ARGUMENTS------------------- input: userDaTaBaSe_pass_word ----OUTPUT---------------------- RSeN4JXTJwVFK6YYnxr6kYzK5I7aDqnJ --- --- $ ./digest.sh input="userDaTaBaSe_pass_word" verbose=false 3oZF4OzyW/0OZEDG/EU+22b+0ZJg9FSc --- * Listing algorithms The <<>> script will list the digest and PBE (Password-Based-Encryption) algorithms available in your Java VM. It receives no arguments and its usage is extremely simple: --- $ ./listAlgorithms.sh DIGEST ALGORITHMS: [MD2, MD5, SHA, SHA-256, SHA-384, SHA-512] PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40] --- Please note that this command will not list any arguments from non-default JCE providers like Bouncy Castle unless you have registered such providers at the JVM installation by copying the provider's jar files to the extensions directory of our JRE installation ($JRE_HOME/lib/ext) and then appending the name of the Provider class at the end of the provider list at the java.security file in $JRE_HOME/lib/security. See {{{./non-default-providers.html}Using Non-Default Providers}} or {{{./bouncy-castle.html}Jasypt + Bouncy Castle}} for more details. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/contributing.apt000066400000000000000000000116511360667575700244070ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Contributing to Jasypt ------- Contributing to Jasypt: Terms In order to contribute to Jasypt, there are some terms with which you must agree: <> * Anyone, with the unique condition that he/she must be a <>, acting in his/her own name, and not being endorsed in their contributed work by any company or government. [] * Note that this condition will not only refer to the ownership of the effort invested in contributing to the project, but also to the fact that no private or public company will be mentioned as a a part of your contribution on the project's website or code, including but not limited to email addresses or package names. [] <> * First and important: your code <>. Also, the addition of any new patches to the codebase should not render it unstable in any way. [] * There should be no compilation warnings. [] * All your code should follow the Java Code Conventions. The only exception for this is that column limit is 120 instead of the usual 80 characters (this is a matter of convenience). [] * Remember that indentation is made of four spaces, not tabs. [] * All your code should compile and run in Java 1.4, and it should be easy to read and understand by a human. [] * All public methods and classes should have comprehensive javadoc, and code should have a reasonable amount of comments in it (when needed, of course, not just comment for comment). [] * All comments, names of classes and variables, log messages, etc. must be in <>. [] <> * First and most important: please, don't feel any obligation to do anything. If you like/want/feel happy about contributing, go for it. If not, don't feel any kind of commitment just for having discussed technical details with the project maintainers or other members, just leave it behind and it will be absolutely fine, even if it is after months and you have already coded thousands of lines. [] * You will be <<<@author>>> for any new classes that you code and also co-author to any existing classes to which you make changes. Of course you can say "no" to this, but unless you do, it is a matter of basic fairness to give the credit and merit to the person who deserves it. [] * Your contributions will be applied as patches that you will send to the project maintainers, and you will have the consideration of in the team page. This means that you will not have read+write direct access to the CVS repository. This is something reserved for developers who are author to a very significant percent of the total code base. Of course, this consideration can change in the future. [] * And importantly: You will have to take the required measures, under your entire responsibility, to <>, and that all the code you contribute is original and will rise no claims over its intellectual property by any third persons or companies. Also, you agree to contribute your code or documentation <>. Contributing to Jasypt: Steps If, after carefully reading the above terms, you are willing to contribute some of your effort to Jasypt, first of all... THANK YOU! The steps you should take are: * 1. First, send an email to the project maintainers talking about the new features or fixes you would like to contribute. Don't forget to include your full name :-). [] * 2. If your contribution is approved, send the project maintainers an email including a copy of the terms above, with your complete name, and stating clearly that you agree with these conditions. [] * 3. If you work for a company which, by the way or place in which your code was written, by your contract terms or by the laws in your contry, could claim any rights (including intellectual property) over your contributed code, you will have to send the project maintainers (either by email from your authorised superiors or by signed fax), a statement indicating that your company agrees with the terms explained in this page, and that it both authorises your contribution to Jasypt and states that will never claim any kind of rights over it. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/dependencies.apt000066400000000000000000000017621360667575700243300ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Dependencies ------- Java Virtual Machine Jasypt needs Java Standard Edition, version 1.6 or higher. If you are going to use strong encryption algorithms (like TripleDES), you may have to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}}. Base dependencies for jasypt Since version 1.7, jasypt does not depend on any external libraries when used with Java version 6 or newer. If you are using Java SE version 5 or older for older Jasypt versions (less than 1.9.3), you will need: * {{{http://www.icu-project.org/}International Components for Unicode (ICU)}} 3.4.4 or higher Also note that from jasypt 1.8, ICU (icu4j) will be used for normalizing Unicode if it is present in classpath, even if Java >= 6 is used (nevertheless, icu4j and <<>> implementations are completely compatible). jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/download.apt000066400000000000000000000045451360667575700235130ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Download ------- Download Jasypt <>: 1.9.3 (May 25th, 2019) [{{{./whatsnew19.html}WHAT'S NEW IN JASYPT 1.9}}] <<{{{https://github.com/jasypt/jasypt}DOWNLOAD JASYPT (from GitHub)}}>> If you are using Maven for building your project, have a look at {{{./maven.html}Jasypt + Maven}} for details on adding a dependency on Jasypt. Jasypt consists of the following artifacts: * <<>> (core) [{{{./changelogs/jasypt/ChangeLog.txt}ChangeLog}}] * Spring integration * <<>> for Spring Framework 2.0 and 2.5 [{{{./changelogs/jasypt-spring2/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Framework 3.0 [{{{./changelogs/jasypt-spring3/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Framework 3.1 [{{{./changelogs/jasypt-spring31/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Framework 4.0 and newer [{{{./changelogs/jasypt-spring4/ChangeLog.txt}ChangeLog}}] * <<>> for Acegi Security 1.0 [{{{./changelogs/jasypt-acegisecurity/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Security 2.x [{{{./changelogs/jasypt-springsecurity2/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Security 3.x and newer [{{{./changelogs/jasypt-springsecurity3/ChangeLog.txt}ChangeLog}}] * <<>> for Spring Security 4.x and newer [{{{./changelogs/jasypt-springsecurity4/ChangeLog.txt}ChangeLog}}] * Hibernate integration * <<>> for Hibernate 3.0, 3.1, 3.2, 3.3, 3.5 and 3.6 [{{{./changelogs/jasypt-hibernate3/ChangeLog.txt}ChangeLog}}] * <<>> for Hibernate 4.x [{{{./changelogs/jasypt-hibernate4/ChangeLog.txt}ChangeLog}}] * <<>> for Hibernate 5.x [{{{./changelogs/jasypt-hibernate5/ChangeLog.txt}ChangeLog}}] * Apache Wicket integration * <<>> for Apache Wicket 1.3 and 1.4 [{{{./changelogs/jasypt-wicket13/ChangeLog.txt}ChangeLog}}] * <<>> for Apache Wicket 1.5 [{{{./changelogs/jasypt-wicket15/ChangeLog.txt}ChangeLog}}] You can also browse the Source Repository {{{./source-repository.html}here}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/easy-usage.apt000066400000000000000000000264171360667575700237510ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Easy usage: the utils ------- Easy usage: the utils The easiest way to use Jasypt is using its encryption tools, which are called <>, because they live in the <> package. They are called because they are ready-to-use, preconfigured digesters and encryptors you can use without knowing much about their configuration. These utils are categorised depending on the task they are intended to do: * General digesting (<<>>) [] * Password encryption (digesting) (<<>>) [] * Text encryption (<<>>) [] * Number encryption (<<>>) [] * Binary encryption (<<>>) (Note that, generally, when we talk about <"password encryption">, we are in fact talking about <"password digesting">, which is the technically correct term) * General digesting * <> which performs message digesting at a binary level, and which results are equivalent to the ones obtained from a <<>> object, although acting in a thread-safe way and implementing an interface more suitable for use in a bean-centric environment. ---------------- ... Digester digester = new Digester(); digester.setAlgorithm("SHA-1"); ... byte[] digest = digester.digest(message); ... ---------------- * Password encryption (digesting) All classes here implement the <<>> interface, so that they can be used interchangeabily if needed. * <> which can be used to both encrypt passwords when users sign up and check input passwords when users sign in. ---------------- ... BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- * <> which implements much higher password security than PasswordEncryptor (at a higher computational cost). ---------------- ... StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- * <> which lets the developer decide the algorithm to be used and whether he/she wants the full secure password encryption mechanism to be applied (as explained {{{./encrypting-passwords.html}here}}) or rather a simple digest to be generated for legacy integration reasons. ---------------- ... ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor(); passwordEncryptor.setAlgorithm("SHA-1"); passwordEncryptor.setPlainDigest(true); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- * Text encryption All classes here implement the <<>> interface, so that they can be used interchangeabily if needed. * <> which allows the user to encrypt and decrypt text data using a normal-strength algorithm. In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- * <> which allows the user to encrypt and decrypt text data using a high-strength algorithm. (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it). In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... StrongTextEncryptor textEncryptor = new StrongTextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... AES256TextEncryptor textEncryptor = new AES256TextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- * Number encryption All classes here implement either the <<>> or the <<>> interfaces, so that they can be used interchangeabily if needed. * <> which allows the user to encrypt and decrypt BigInteger objects using a normal-strength algorithm. In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... BasicIntegerNumberEncryptor integerEncryptor = new BasicIntegerNumberEncryptor(); integerEncryptor.setPassword(myEncryptionPassword); ... BigInteger myEncryptedNumber = textEncryptor.encrypt(myNumber); ... BigInteger plainNumber = textEncryptor.decrypt(myEncryptedNumber); ... ---------------- * <> which allows the user to encrypt and decrypt BigInteger objects using a high-strength algorithm. (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it). In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... StrongIntegerNumberEncryptor integerEncryptor = new StrongIntegerNumberEncryptor(); integerEncryptor.setPassword(myEncryptionPassword); ... BigInteger myEncryptedNumber = integerEncryptor.encrypt(myNumber); ... BigInteger plainNumber = integerEncryptor.decrypt(myEncryptedNumber); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... BigInteger myNumber = ...; ... AES256IntegerNumberEncryptor numberEncryptor = new AES256IntegerNumberEncryptor(); numberEncryptor.setPassword(myEncryptionPassword); ... BigInteger myEncryptedNumber = numberEncryptor.encrypt(myNumber); ... BigInteger plainNumber = numberEncryptor.decrypt(myEncryptedNumber); ... ---------------- * <> which allows the user to encrypt and decrypt BigDecimal objects using a normal-strength algorithm. In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... BasicDecimalNumberEncryptor decimalEncryptor = new BasicDecimalNumberEncryptor(); decimalEncryptor.setPassword(myEncryptionPassword); ... BigDecimal myEncryptedNumber = decimalEncryptor.encrypt(myNumber); ... BigDecimal plainNumber = decimalEncryptor.decrypt(myEncryptedNumber); ... ---------------- * <> which allows the user to encrypt and decrypt BigDecimal objects using a high-strength algorithm. (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it). In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... StrongDecimalNumberEncryptor decimalEncryptor = new StrongDecimalNumberEncryptor(); decimalEncryptor.setPassword(myEncryptionPassword); ... BigDecimal myEncryptedNumber = decimalEncryptor.encrypt(myNumber); ... BigDecimal plainNumber = decimalEncryptor.decrypt(myEncryptedNumber); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... BigDecimal myNumber = ...; ... AES256DecimalNumberEncryptor numberEncryptor = new AES256DecimalNumberEncryptor(); numberEncryptor.setPassword(myEncryptionPassword); ... BigDecimal myEncryptedNumber = numberEncryptor.encrypt(myNumber); ... BigDecimal plainNumber = numberEncryptor.decrypt(myEncryptedNumber); ... ---------------- * Binary encryption All classes here implement the <<>> interface, so that they can be used interchangeabily if needed. * <> which allows the user to encrypt and decrypt byte[] objects using a normal-strength algorithm. In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... BasicBinaryEncryptor binaryEncryptor = new BasicBinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBinary = binaryEncryptor.encrypt(myBinary); ... String plainBinary = binaryEncryptor.decrypt(myEncryptedBinary); ... ---------------- * <> which allows the user to encrypt and decrypt byte[] objects using a high-strength algorithm. (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it). In order to be able to encrypt and decrypt, this encryptor has to be set a password first. ---------------- ... StrongBinaryEncryptor binaryEncryptor = new StrongBinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBinary = binaryEncryptor.encrypt(myBinary); ... String plainBinary = binaryEncryptor.decrypt(myEncryptedBinary); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... AES256BinaryEncryptor binaryEncryptor = new AES256BinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBytes = binaryEncryptor.encrypt(myBytes); ... byte[] plainBytes = binaryEncryptor.decrypt(myEncryptedBytes); ... ---------------- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/encrypting-binaries.apt000066400000000000000000000132771360667575700256620ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting binaries ------- Encrypting binaries Jasypt offers support for performing PBE (Password Based Encryption) operations on binaries (byte[] objects). This is offered through the <<>> interface and its default implementation, <>. * Usage Assuming that you will be using the default implementation, once the <<>> instance has been created, this is how it will work: ** Configuration The algorithm, password and key-obtention iterations can take values in any of these ways: * Using its default values (except for password). * Setting an <<>> object which provides new configuration values. {{{./advancedconfiguration.html}Learn More}}. * Calling the corresponding <<>>, <<>>, <<>>, <<>>, <<>>, <<>> or <<>> methods. And the actual values to be used for initialization will be established by applying the following priorities: * First, the default values are considered (except for password). * Then, if a <<>> object has been set with <<>>, the non-null values returned by its <<>> methods override the default values. * Finally, if the corresponding <<>> method has been called on the encryptor itself for any of the configuration parameters, the values set by these calls override all of the above. ** Initialization Before it is ready to encrypt, an object of this class has to be . Initialisation happens: * When <<>> is called. * When <<>> or <<>> are called for the first time, if <<>> has not been called before * Once an encryptor has been initialised, trying to change its configuration willresult in an <<>> being thrown. ** Usage An encryptor may be used for: * , by calling the <<>> method. * , by calling the <<>> method. <>. This enforces security by difficulting brute force attacks on sets of data at a time and forcing attackers to perform a brute force attack on each separate piece of encrypted data. The same applies when a random IV generator is used: the IV should be random and only used one time, so org.jasypt.RandomIvGenerator is the recommended one. ** Learn more To learn more about the mechanisms involved in encryption, read {{{http://www.rsasecurity.com/rsalabs/node.asp?id=2127}PKCS #5: Password-Based Cryptography Standard}}. * Code examples Easiest use: the <<>> util class: ---------------- ... BasicBinaryEncryptor binaryEncryptor = new BasicBinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBytes = binaryEncryptor.encrypt(myBytes); ... byte[] plainBytes = binaryEncryptor.decrypt(myEncryptedBytes); ... ---------------- More security: the <<>> util class with a much more secure (but slower!) algorithm (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it): ---------------- ... StrongBinaryEncryptor binaryEncryptor = new StrongBinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBytes = binaryEncryptor.encrypt(myBytes); ... byte[] plainBytes = binaryEncryptor.decrypt(myEncryptedBytes); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... AES256BinaryEncryptor binaryEncryptor = new AES256BinaryEncryptor(); binaryEncryptor.setPassword(myEncryptionPassword); ... byte[] myEncryptedBytes = binaryEncryptor.encrypt(myBytes); ... byte[] plainBytes = binaryEncryptor.decrypt(myEncryptedBytes); ... ---------------- All these classes are in fact pre-configured, easy-to-use versions of <<>>, so let's use the original class for total control: ------------------ ... StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setPassword("jasypt"); // we HAVE TO set a password encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); // optionally set the algorithm ... byte[] encryptedBytes = encryptor.encrypt(myBytes); ... byte[] plainBytes = encryptor.decrypt(encryptedBytes); // myBytes.equals(plainBytes) ... ------------------ And we can even use a pooled version for higher performance in multi-processor/multi-core systems: --- ... PooledPBEByteEncryptor encryptor = new PooledPBEByteEncryptor(); encryptor.setPoolSize(4); // This would be a good value for a 4-core system encryptor.setPassword("jasypt"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); ... byte[] encryptedBytes = encryptor.encrypt(myBytes); ... --- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/encrypting-configuration.apt000066400000000000000000000104701360667575700267250ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting application configuration files ------- Encrypting application configuration files Jasypt offers support for encrypted application configuration in three different ways: * <<.properties files>>: Jasypt provides the <<>> class for loading, managing and transparently decrypting encrypted values in <<<.properties>>> files, allowing the mix of both encrypted and not-encrypted values in the same file. [] * <>: Jasypt can integrate into the configuration system of the Spring Framework (2.x and 3.x) and transparently decrypt <<<.properties>>> files used by Spring applications. Learn more: {{{./spring2.html}Spring 2.x}}, {{{./spring3.html}Spring 3.0}}, {{{./spring31.html}Spring 3.1}}, {{{./spring31.html}Spring 4.0}}. [] * <>: Jasypt provides two classes for Hibernate (DriverManager- and C3P0-based) which allow the basic datasource parameters (driver, url, username and password) to be written in an encrypted manner in the hibernate.cfg.xml file. {{{./hibernate.html}Learn more}}. This way, jasypt supports the encryption of sensitive configuration data in multiple scenarios (Hibernate-, Spring-, both- or neither-based applications). <>. You can compute this values using the {{{./cli.html}CLI tools}}. Here you may think: <"wait... I can encrypt values in my configuration files, ok, but... I still need a password (the encryption password) to decrypt them! Where can I store it safely?">. That is correct, you still need one password, but this time it is the one, under jasypt control, and thus, configurable in many other more secure ways (especially recommended would be {{{./advancedconfiguration.html}environment variables}} or {{{./webconfiguration.html}web PBE configuration}}...). * EncryptableProperties By using an <<>> object, an application would be able to correctly read and use a .properties file like this: --- datasource.driver=com.mysql.jdbc.Driver datasource.url=jdbc:mysql://localhost/reportsdb datasource.username=reportsUser datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) --- Note that the database password is encrypted (in fact, any other property could also be encrypted, be it related with database configuration or not). How do we read this value? like this: --- /* * First, create (or ask some other component for) the adequate encryptor for * decrypting the values in our .properties file. */ StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("jasypt"); // could be got from web, env variable... encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); encryptor.setIvGenerator(new RandomIvGenerator()); /* * Create our EncryptableProperties object and load it the usual way. */ Properties props = new EncryptableProperties(encryptor); props.load(new FileInputStream("/path/to/my/configuration.properties")); /* * To get a non-encrypted value, we just get it with getProperty... */ String datasourceUsername = props.getProperty("datasource.username"); /* * ...and to get an encrypted value, we do exactly the same. Decryption will * be transparently performed behind the scenes. */ String datasourcePassword = props.getProperty("datasource.password"); // From now on, datasourcePassword equals "reports_passwd"... --- For decrypting the encrypted value, we just had to access it with <<>>, just as with any other non-encrypted value. <<>> objects can receive as a constructor argument both an <<>> implementation or an <<>> object. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/encrypting-numbers.apt000066400000000000000000000157151360667575700255400ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting numbers ------- Encrypting numbers Jasypt offers support for performing PBE (Password Based Encryption) operations on numbers. This is offered through the <<>> and <<>> interfaces and their respective default implementations, <> and <>. * Basics Jasypt uses the byte (binary) encryption mechanisms as a basis for text encryption. Note that encrypted numbers will need much more digits for its representation than the original numbers from which they come, and so they will also need more space for being stored. For example, a 4-byte integer will probably have a size of no less than 16 bytes, once encrypted. . * Usage Assuming that you will be using the default implementations, once a <<>> or <<>> instance has been created, this is how it will work: ** Configuration The algorithm, password and key-obtention iterations can take values in any of these ways: * Using its default values (except for password). * Setting an <<>> object which provides new configuration values. {{{./advancedconfiguration.html}Learn More}}. * Calling the corresponding <<>>, <<>>, <<>>, <<>>, <<>>, <<>> or <<>> methods. And the actual values to be used for initialization will be established by applying the following priorities: * First, the default values are considered (except for password). * Then, if a <<>> object has been set with <<>>, the non-null values returned by its <<>> methods override the default values. * Finally, if the corresponding <<>> method has been called on the encryptor itself for any of the configuration parameters, the values set by these calls override all of the above. ** Initialization Before it is ready to encrypt, an object of this class has to be . Initialisation happens: * When <<>> is called. * When <<>> or <<>> are called for the first time, if <<>> has not been called before * Once an encryptor has been initialised, trying to change its configuration willresult in an <<>> being thrown. ** Usage An encryptor may be used for: * , by calling the <<>> method. * , by calling the <<>> method. <>. This enforces security by difficulting brute force attacks on sets of data at a time and forcing attackers to perform a brute force attack on each separate piece of encrypted data. The same applies when a random IV generator is used: the IV should be random and only used one time, so org.jasypt.RandomIvGenerator is the recommended one. ** Learn more To learn more about the mechanisms involved in encryption, read {{{http://www.rsasecurity.com/rsalabs/node.asp?id=2127}PKCS #5: Password-Based Cryptography Standard}}. * Code examples Easiest use: the <<>> and <<>> util classes: ---------------- ... BigInteger myNumber = ...; ... BasicIntegerNumberEncryptor numberEncryptor = new BasicIntegerNumberEncryptor(); numberEncryptor.setPassword(myEncryptionPassword); ... BigInteger myEncryptedNumber = numberEncryptor.encrypt(myNumber); ... BigInteger plainNumber = numberEncryptor.decrypt(myEncryptedNumber); ... ---------------- More security: the <<>> and <<>> util classes with a much more secure (but slower!) algorithm (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use them): ---------------- ... BigDecimal myNumber = ...; ... StrongDecimalNumberEncryptor numberEncryptor = new StrongDecimalNumberEncryptor(); numberEncryptor.setPassword(myEncryptionPassword); ... BigDecimal myEncryptedNumber = numberEncryptor.encrypt(myNumber); ... BigDecimal plainNumber = numberEncryptor.decrypt(myEncryptedNumber); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... BigDecimal myNumber = ...; ... AES256DecimalNumberEncryptor numberEncryptor = new AES256DecimalNumberEncryptor(); numberEncryptor.setPassword(myEncryptionPassword); ... BigDecimal myEncryptedNumber = numberEncryptor.encrypt(myNumber); ... BigDecimal plainNumber = numberEncryptor.decrypt(myEncryptedNumber); ... ---------------- All these classes are in fact pre-configured, easy-to-use versions of their corresponding full-featured classes <<>> and, <<>> so let's use the original classes for total control: ------------------ ... BigDecimal myNumber = ...; ... StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setPassword("jasypt"); // we HAVE TO set a password encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); // optionally set the algorithm ... BigDecimal myEncryptedNumber = encryptor.encrypt(myNumber); ... BigDecimal plainNumber = encryptor.decrypt(myEncryptedNumber); ... ------------------ And we can even use a pooled version for higher performance in multi-processor/multi-core systems: --- ... BigInteger myNumber = ...; ... PooledPBEBigIntegerEncryptor encryptor = new PooledPBEBigIntegerEncryptor(); encryptor.setPoolSize(4); // This would be a good value for a 4-core system encryptor.setPassword("jasypt"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); ... BigInteger myEncryptedNumber = encryptor.encrypt(myNumber); ... BigInteger plainNumber = encryptor.decrypt(myEncryptedNumber); ... --- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/encrypting-passwords.apt000066400000000000000000000141041360667575700261010ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting passwords ------- Encrypting passwords If you want to read about how passwords should be encrypted, how you would defend from attacks on your user password database, and why you should use jasypt for encrypting your passwords, have a look at this article: {{{./howtoencryptuserpasswords.html}How to Encrypt User Passwords}}. * Digest creation process with jasypt's Standard\[Byte\|String\]Digester The steps taken in jasypt's standard digesters for creating digests are: [[1]]A salt of the specified size is generated (see <>). If salt size is zero, no salt will be used. It is advisable that you use a random salt generator like <> (which is the default) for higher security. [[2]]The salt bytes are appended at the beginning of the message. [[3]]The hash function is applied to the salt and message altogether, and then to the results of the function itself, as many times as specified (iterations). [[4]]If using a random salt generator, the salt is appended at the beginning of the hash result. Put schematically in bytes: * DIGEST = \|<>\|..(ssb)..\|<>\|<>\|<>\|<>\|...\|<>\| * <>: salt bytes (plain, not digested). <(Only if using a random salt generator)>. * ssb: salt size in bytes. * <>: bytes resulting from hashing (see below). [] * |<>|<>|<>|...|<>| = (((..(it)..(<>|<>|<>|...|<>|)))) * : Hash function (algorithm). * it: Number of iterations. * <>: Input for hashing (see below). [] * |<>|<>|<>|...|<>| = |<>|..(ssb)..|<>|<>|<>|<>...|<>| * <>: salt bytes (plain, not digested). * ssb: salt size in bytes. * <>: message bytes. <> Because of this, in this case the result of the <<>> method will contains both the salt and the digest of salt+message, so that another digest operation can be performed with the same salt on a different message to check if both messages match (all of which will be managed automatically by the <<>> method). Also, when using StandardStringDigester, the resulting digest Strings are BASE64 encoded (or hexadecimal, if you prefer) to avoid charset issues. This output encoding can be chosen with the <<>> method. * RFC2307 password encryption for LDAP systems Many LDAP systems (e.g. OpenLDAP) use password encryption schemes different to jasypt's default one. These are mainly derived from the schemes defined in RFC2307, like for example <> (Salted SHA). Salted RFC2307-oriented algorithms require an inversion in the positioning of the salt during the digest operation. Jasypt supports this since version 1.7, and provides a set of classes in the <<>> package for the easy creation and matching of SSHA, SMD5 and other password encryption schemes of common use in LDAP systems. Refer to these classes' {{{./javadoc.html}JavaDoc}} for more details. * Code examples Easiest use: the <<>> util class: ---------------- ... BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- More security: the <<>> util class with a much more secure (but slower!) algorithm: ---------------- ... StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- A little bit more control on encryptor configuration: the <<>> class: ---------------- ... ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor(); passwordEncryptor.setAlgorithm("SHA-1"); passwordEncryptor.setPlainDigest(true); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ... ---------------- All these classes are in fact pre-configured, easy-to-use versions of <<>>, so let's use the original class for total control: ------------------ ... StandardStringDigester digester = new StandardStringDigester(); digester.setAlgorithm("SHA-1"); // optionally set the algorithm digester.setIterations("50000"); // increase security by performing 50000 hashing iterations ... String digest = digester.digest(userPassword); ... if (digester.matches(inputPassword, digest)) { // correct! } else { // bad login! } ... ------------------ And we can even use a pooled version for higher performance in multi-processor/multi-core systems: --- ... PooledStringDigester digester = new PooledStringDigester(); digester.setPoolSize(4); // This would be a good value for a 4-core system digester.setAlgorithm("SHA-1"); digester.setIterations("50000"); ... String digest = digester.digest(userPassword); ... if (digester.matches(inputPassword, digest)) { // correct! } else { // bad login! } ... --- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/encrypting-texts.apt000066400000000000000000000142001360667575700252200ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Encrypting texts ------- Encrypting texts Jasypt offers support for performing PBE (Password Based Encryption) operations on texts. This is offered through the <<>> interface and its default implementation, <>. * Basics Jasypt uses the byte (binary) encryption mechanisms as a basis for text encryption, with the following specificity: * All the String results (of encryption) are encoded in <> (or <>, if you prefer), and thus can be safely stored as US-ASCII characters. This output encoding can be chosen with the <<>> method. * Usage Assuming that you will be using the default implementation, once the <<>> instance has been created, this is how it will work: ** Configuration The algorithm, password and key-obtention iterations can take values in any of these ways: * Using its default values (except for password). * Setting an <<>> object which provides new configuration values. {{{./advancedconfiguration.html}Learn More}}. * Calling the corresponding <<>>, <<>>, <<>>, <<>>, <<>>, <<>> or <<>> methods. And the actual values to be used for initialization will be established by applying the following priorities: * First, the default values are considered (except for password). * Then, if a <<>> object has been set with <<>>, the non-null values returned by its <<>> methods override the default values. * Finally, if the corresponding <<>> method has been called on the encryptor itself for any of the configuration parameters, the values set by these calls override all of the above. ** Initialization Before it is ready to encrypt, an object of this class has to be . Initialisation happens: * When <<>> is called. * When <<>> or <<>> are called for the first time, if <<>> has not been called before * Once an encryptor has been initialised, trying to change its configuration willresult in an <<>> being thrown. ** Usage An encryptor may be used for: * , by calling the <<>> method. * , by calling the <<>> method. <>. This enforces security by difficulting brute force attacks on sets of data at a time and forcing attackers to perform a brute force attack on each separate piece of encrypted data. The same applies when a random IV generator is used: the IV should be random and only used one time, so org.jasypt.RandomIvGenerator is the recommended one. ** Learn more To learn more about the mechanisms involved in encryption, read {{{http://www.rsasecurity.com/rsalabs/node.asp?id=2127}PKCS #5: Password-Based Cryptography Standard}}. * Code examples Easiest use: the <<>> util class: ---------------- ... BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- More security: the <<>> util class with a much more secure (but slower!) algorithm (you may need to download and install the {{{http://java.sun.com/javase/downloads}Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files}} to use it): ---------------- ... StrongTextEncryptor textEncryptor = new StrongTextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- More security: the <<>> util class with a much more secure algorithm: PBEWithHMACSHA512AndAES_256, (you need Java 8 at least to use it): ---------------- ... AES256TextEncryptor textEncryptor = new AES256TextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); ... String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ... ---------------- All these classes are in fact pre-configured, easy-to-use versions of <<>>, so let's use the original class for total control: ------------------ ... StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("jasypt"); // we HAVE TO set a password encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); // optionally set the algorithm encryptor.setIvGenerator(new RandomIvGenerator()); // for PBE-AES-based algorithms, the IV generator is MANDATORY ... String encryptedText = encryptor.encrypt(myText); ... String plainText = encryptor.decrypt(encryptedText); // myText.equals(plainText) ... ------------------ And we can even use a pooled version for higher performance in multi-processor/multi-core systems: --- ... PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); // This would be a good value for a 4-core system encryptor.setPassword("jasypt"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); ... String encryptedText = encryptor.encrypt(myText); ... --- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/features.apt000066400000000000000000000116471360667575700235230ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Features ------- Features * Jasypt provides you with easy unidirectional (digest) and bidirectional encryption techniques. [] * Open API for <>, and not only the default Java VM one. Jasypt can be easily used with well-known providers like {{{http://www.bouncycastle.org}Bouncy Castle}}. {{{./non-default-providers.html}Learn more}}. [] * <>. {{{./encrypting-passwords.html}Learn more}}. [] * <>. Jasypt allows the digest and encryption of binaries (byte arrays). Encrypt your objects or files when needed (for being sent over the net, for example). [] * <>. Besides texts and binaries, it allows the digest and encryption of numeric values (BigInteger and BigDecimal, other numeric types are supported when encrypting for Hibernate persistence). {{{./encrypting-numbers.html}Learn more}}. [] * Completely <>. [] * Support for encryptor/digester pooling, in order to achieve <>. [] * Includes a <> for better manageability in size-restrictive environments like mobile platforms. [] * Provides both <> for users new to encryption, and also <>, for power-users. [] * {{{http://www.hibernate.org}Hibernate 3, 4 and 5}} optional integration for persisting fields of your mapped entities in an encrypted manner. <>, and it remains transparent for the rest of the application (useful for sensitive personal data, databases with many read-enabled users...). Encrypt texts, binaries, numbers, booleans, dates... {{{./hibernate.html}Learn more}}. [] * Seamlessly integrable into a {{{http://www.springframework.org}Spring}} application, with specific integration features for Spring 2, Spring 3.0, Spring 3.1 and Spring 4.0. All the digesters and encryptors in jasypt are designed to be easily used (instantiated, dependency-injected...) from Spring. And, because of their being thread-safe, they <>. Learn more: {{{./spring2.html}Spring 2}}, {{{./spring3.html}Spring 3.0}}, {{{./spring31.html}Spring 3.1}}, {{{./spring31.html}Spring 4.0}}. [] * {{{http://static.springframework.org/spring-security/site/}Spring Security (formerly Acegi Security)}} optional integration for performing password encryption and matching tasks for the security framework, improving the security of your users' passwords by using <> and providing you with a higher degree of <>. {{{./springsecurity.html}Learn more}}. [] * Provides <>, including sensitive information like database passwords. Seamlessly integrate encrypted configuration into plain, Spring-based and/or Hibernate-enabled applications. {{{./encrypting-configuration.html}Learn more}}. [] * Provides easy to use <> to allow developers initialise their encrypted data and include encryption/decryption/digest operations in maintenance tasks or scripts. {{{./cli.html}Learn more}}. [] * <>, for more robust encryption of URLs in your secure applications. [] * <>, to allow developers to better understand what they are really doing to their data. [] * Robust charset support, designed to adequately encrypt and digest texts whichever the original charset is. <> with no encoding or platform issues. [] * Very high level of configuration capabilities: The developer can implement tricks like instructing an "encryptor" to ask a, for example, remote HTTPS server for the password to be used for encryption. <>. {{{./advancedconfiguration.html}Learn more}}. Want to know more? To know more, check the {{{./faq.html}Frequently Asked Questions}} page. If you have questions, there is a {{{http://stackoverflow.com/questions/tagged/jasypt}"jasypt" tag in StackOverflow}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/general-usage.apt000066400000000000000000000245241360667575700244220ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - General Usage ------- General Usage This section will teach you about the tools jasypt offers you when the utilities found in the {{{./easy-usage.html}easy usage}} page are not enough for your needs. * Digesters Digesters are classes specialised in creating <> (also called <>) from input. Message digests are the results of (or ) functions, and they are <>, this is, starting from a message digest, the original message cannot be reconstructed. Because of this, message digests are very adequate for <>. In fact, in some countries, it is illegal to store a user's password in an unencrypted way, and even encrypted in a reversible (bi-directional) way. Digesters in jasypt live in the <> package, which is composed of the following interfaces: * <> for creating digests from byte array input. * <> for creating digests from String input. And the following standard implementations: * <>: very configurable and extremely secure implementation of ByteDigester, implemented following the directives given in {{{http://www.rsasecurity.com/rsalabs/node.asp?id=2127}PKCS #5: Password-Based Cryptography Standard}}. * <>: String counterpart to StandardByteDigester, receiving String input and returning charset-safe, BASE64 (or hexadecimal) encoded String output. ...with their corresponding pool-based implementations for high performance in multi-processor/multi-core systems: * <>: same API as <>, but in fact contains a pool of these objects that are used to serve digest/check requests in round-robin. * <>: same API as <>, but in fact contains a pool of these objects that are used to serve digest/check requests in round-robin. Using them can be very simple: ------------------ ... StandardStringDigester digester = new StandardStringDigester(); digester.setAlgorithm("SHA-1"); // optionally set the algorithm digester.setIterations(50000); // increase security by performing 50000 hashing iterations ... String digest = digester.digest(myMessage); ... ------------------ These digesters, both standard and pooled, implement a coherent and secure set of default configuration values, but they can be additionally configured in two ways: * By calling to its <<>> methods (algorithm, provider, salt size, etc.) * By setting a <> object which configures the digester. A default implementation of this interface is supplied (<<>>), but the user can create his/her own one to be able to retrieve configuration parameters in whichever ways he/she needs. <> Pooled digesters have exactly the same API as their non-pooled <<>> relatives --so they can be used interchangeably-- but add a new required configuration method called <<>> which establishes the amount of digesters they will internally hold. --- ... PooledStringDigester digester = new PooledStringDigester(); digester.setPoolSize(4); // This would be a good value for a 4-core system digester.setAlgorithm("SHA-1"); digester.setIterations(50000); ... String digest = digester.digest(myMessage); ... --- These pooled objects will use their internal <<>> digesters to serve the requests in round-robin, so the amount of thread blocking caused by the synchronised code in the artifacts is reduced to a minimum. These implementations do not create new threads, so they can be safely used in container-controlled environments which do not allow the creation of new threads. The pool size recommended for a specific application and machine depends on many factors, but will be approximately equal to the number of processors/cores in the machine. <> Please refer to the {{{./javadoc.html}JavaDoc}} for more information about usage and functionality. * Encryptors Encryptors are classes specialised in performing <> encryption operations. This is, they can both encrypt plain data and decrypt encrypted data. The relevant interfaces for encryption in jasypt live in the <> package, and are: * <> for encryption and decryption of byte arrays. * <> for encryption and decryption of Strings. * <> for encryption and decryption of BigIntegers. * <> for encryption and decryption of BigDecimals. Jasypt provides implementations for one type of encryption: <>. ** Password-Based Encryption (PBE) Password-Based encryption is performed by means of generating an from a user-supplied <>, and feeding an encryption algorithm with both the input and the generated key. Keys are usually obtained by applying some hash function to the password. So, <> before being used for encryption or decryption operations. The relevant interfaces for PBE in jasypt live in the <> package, and are: * <> for password-based encryption and decryption of byte arrays. * <> for password-based encryption and decryption of Strings. * <> for password-based encryption and decryption of BigIntegers. * <> for password-based encryption and decryption of BigDecimals. And the following standard implementations: * <>: very configurable and extremely secure implementation of PBEByteEncryptor, implemented following the directives given in {{{http://www.rsasecurity.com/rsalabs/node.asp?id=2127}PKCS #5: Password-Based Cryptography Standard}}. * <>: String counterpart to StandardPBEByteEncryptor, receiving String input and returning charset-safe, BASE64 (or hexadecimal) encoded String output as encryption results. * <>: Equivalent to StandardPBEByteEncryptor, receiving BigInteger input and returning BigInteger output. * <>: Equivalent to StandardPBEByteEncryptor, receiving BigDecimal input and returning BigDecimal output. ...with their corresponding pool-based implementations for high performance in multi-processor/multi-core systems: * <>: same API as <>, but in fact contains a pool of these objects that are used to serve encrypt/decrypt requests in round-robin. * <>: same API as <>, but in fact contains a pool of these objects that are used to serve encrypt/decrypt requests in round-robin. * <>: same API as <>, but in fact contains a pool of these objects that are used to serve encrypt/decrypt requests in round-robin. * <>: same API as <>, but in fact contains a pool of these objects that are used to serve encrypt/decrypt requests in round-robin. It's basic usage can be very simple: ------------------ ... StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("jasypt"); // we HAVE TO set a password encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); // optionally set the algorithm encryptor.setIvGenerator(new RandomIvGenerator()); // for PBE-AES-based algorithms, the IV generator is MANDATORY ... String encryptedText = encryptor.encrypt(myText); ... String plainText = encryptor.decrypt(encryptedText); // myText.equals(plainText) ... ------------------ As with digesters, Standard*Encryptors implement a coherent and secure set of default configuration values (except for the password), but they can also be additionally configured in two ways: * By calling to its <<>> methods (algorithm, provider, password, salt, IV, etc...) * By setting a <> object which configures the digester. A default implementation of this interface is supplied (<<>>), but the user can create his/her own one to be able to retrieve configuration parameters in whichever ways he/she needs (for instance, retrieve the password from a remote server). <> Pooled encryptors have exactly the same API as their non-pooled <<>> relatives --so they can be used interchangeably-- but add a new required configuration method called <<>> which establishes the amount of encryptors they will internally hold. --- ... PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); // This would be a good value for a 4-core system encryptor.setPassword("jasypt"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); ... String encryptedText = encryptor.encrypt(myText); ... --- These pooled objects will use their internal <<>> encryptors to serve the requests in round-robin, so the amount of thread blocking caused by the synchronised code in the artifacts is reduced to a minimum. These implementations do not create new threads, so they can be safely used in container-controlled environments which do not allow the creation of new threads. The pool size recommended for a specific application and machine depends on many factors, but will be approximately equal to the number of processors/cores in the machine. <> Please refer to the {{{./javadoc.html}JavaDoc}} for more information about usage and functionality. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/hibernate.apt000066400000000000000000000412111360667575700236340ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Hibernate 3, 4 and 5 ------- Integrating Jasypt with Hibernate 3.x, 4.x or 5.x Jasypt provides the <<>>, <<>> and <<>> artifacts for Hibernate integration. Since jasypt 1.9.0, these artifacts must be added to your classpath separately. These integration libraries include several Hibernate <> implementations that allow one or several of the properties in a mapped Hibernate entity to be declared as being of an . Types allowed to be stored as encrypted include strings, binaries (byte arrays), numeric types, booleans and dates. Jasypt also provides two (<<>>) implementations which let the user declare the datasource parameters in an encrypted manner. * Transparent data encryption with Jasypt and Hibernate Thanks to the use of custom <> implementations, jasypt allows your applications to store encrypted data for their hibernate mapped entities, but <> for the application's logic. This can be useful for encrypting personal data, private messages, etc, so that it is avoided that anyone with read access to the "critical" tables can read all of its contents. For encryption at Hibernate, jasypt uses its capabilities, and <> can be used to encrypt data, even encryptors created by the user. But <>: security standards establish that two different encryption operations on the same data should not return the same value (due to the use of a random salt). Because of this, none of the fields that are set to be encrypted when persisted can be a part of a WHERE clause in your search queries for the entity they belong to. ** Encryption types *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ ||<> ||<> ||<> || <> | || || ||(<<>>) || | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARBINARY, BLOB |<<>> |Honors <<>>. | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |NUMERIC, NUMBER |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |NUMERIC, NUMBER |<<>> |Needs an additional <<>> property. | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> | | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ |<<>> |VARCHAR, CLOB, TEXT |<<>> |Offers an additional <<>> property. | *------------------+---------------------------------+---------------------------------------+-------------------------------------------------------------------+ When storing an encrypted field, note that you will need a higher amount of space to store the result of the encryption than the space you would need to store the unencrypted piece of data. This is specially important when encrypting with <<>> or <<>>, as NUMBER and NUMERIC fields are defined by means of digits, not bytes, and thus the difference of size will be much higher than intuitively expected (normally you won't use a field smaller than a NUMERIC(60) to store an encrypted normal-size BigInteger). ** Configuration Setting jasypt to encrypt data with hibernate requires two separate actions: [[1]] <>. [[2]] <>. *** Configuring the Hibernate mapping The Hibernate mapping file can be configured in two different ways: [[A]] <>, declaring the encryptor parameters in the mapping itself (password, algorithm, providerName, etc). This is not very recommended (the mapping file does not seem like a right place for a password) but can be useful in some situations. When this method is selected, the encryptor implementation used is always a <>. ------------------- ... PBEWithMD5AndTripleDES jasypt 1000 ... ... ... ... ------------------- Note: only "password" is a required parameter.\ If this configuration method is used, it is not necessary to an encryptor to Hibernate (like explained below). [[B]] <>, which will be with a specific . This way, all we will have to use in the mapping file is this name (<<>>). ------------------- ... strongHibernateStringEncryptor ... ... ... ... ------------------- *** Providing the encryptor to Hibernate If we have chosen to use the parameter in our Hibernate mapping file, we will need to bind somehow an encryptor object to that name. This can be done in two different manners, depending on whether we are using an IoC container like Spring or not. Using this way of configuring encryption allows us to use pool-based versions of the encryptor (like <<>>), which will enhance performance in multi-processor/multi-core systems. * <> we simply need to create our encryptor, and then a object to wrap it and set a for it: ------------------- PBEWithMD5AndTripleDES jasypt 4 strongHibernateStringEncryptor ------------------- Also, we can do it all in the declaration, if we don't want to use the outside of Hibernate and we are OK with the standard encryptor implementation. Also be aware that this approach uses a StandardPBEStringEncryptor instead of a pool-based one, and so performace could be affected in multi-processor systems: ------------------- strongHibernateStringEncryptor PBEWithMD5AndTripleDES jasypt ------------------- * <>, we will have to use the singleton directly, registering our encryptor at application initialization like this (for example, inside a for a webapp): ------------------- StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor(); ... HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("strongHibernateStringEncryptor", strongEncryptor); ------------------- *** Using annotations Alternatively, we may have chosen to use annotations for mapping our entities instead of separate XML mapping files. If it has been so, we can still use jasypt to encrypt our data. All we will have to do is, first, define the encryption type with a <<@TypeDef>> annotation, which could be either inside the persisted entity class or inside a <<@TypeDefs>> declaration in a separate <<>> file: ------------------- @TypeDef( name="encryptedString", typeClass=EncryptedStringType.class, parameters= { @Parameter(name="encryptorRegisteredName", value="myHibernateStringEncryptor") } ) ------------------- ...and then simply map our property with the already declared type: ------------------- @Type(type="encryptedString") public String getAddress() { return address; } ------------------- * Encrypting the database password in hibernate.cfg.xml For those applications that define datasources in Hibernate's <<>> file, Jasypt provides two (<<>>) implementations which let the user declare the datasource parameters (driver, url, username and password) in an encrypted manner: * <<>>, which extends Hibernate's connection provider (a very simplistic pool implementation). [] * <<>>, which extends Hibernate's connection provider. [] They are used like this in <<>>: --- org.jasypt.hibernate4.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider configurationHibernateEncryptor jdbc:mysql://localhost/reportsdb com.mysql.jdbc.Driver reportsUser ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) 12 true org.hibernate.dialect.MySQLDialect --- In this configuration, Hibernate is told to use Jasypt's DriverManager-based connection provider and is passed a set of configuration parameters which contain an encrypted value, the <<>> property. Then, Hibernate is also told about which is the encryptor object to be used for decrypting the encrypted parameters (<<>>). This encryptor object should have been registered beforehand as a <>, as explained in the <'Transparent data encryption'> section. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/hibernate3.apt000066400000000000000000000002741360667575700237230ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Hibernate ------- This page has been moved {{{./hibernate.html}Go to the Hibernate integration page}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/index.apt000066400000000000000000000046301360667575700230060ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Main ------- <> (May 25th, 2019) [{{{./download.html}DOWNLOAD and ChangeLogs}}] [{{{./whatsnew19.html}WHAT'S NEW IN JASYPT 1.9}}] Java Simplified Encryption Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. * High-security, standards-based encryption techniques, both for unidirectional and bidirectional encryption. Encrypt passwords, texts, numbers, binaries... * Transparent integration with <>. * Suitable for integration into <>-based applications and also transparently integrable with <>. * Integrated capabilities for encrypting the configuration of applications (i.e. datasources). * Specific features for <> in multi-processor/multi-core systems. * Open API for use with any JCE provider. * {{{./features.html}...and much more}} Have a look at the complete set of <<{{{./features.html}Jasypt Features}}>> or check the <<{{{./faq.html}FAQ}}>>. With Jasypt, encrypting and checking a password can be as simple as... ---------------- StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(userPassword); ... if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) { // correct! } else { // bad login! } ---------------- ...encrypting and decrypting a text... ---------------- AES256TextEncryptor textEncryptor = new AES256TextEncryptor(); textEncryptor.setPassword(myEncryptionPassword); String myEncryptedText = textEncryptor.encrypt(myText); ... String plainText = textEncryptor.decrypt(myEncryptedText); ---------------- ...and what about encrypting some sensitive data directly from Hibernate? ---------------- ... ... ---------------- But of course, besides easy, <>. You will be able to choose encryption algorithms, salt generation, initialization vector generation and many more advanced features... jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/javadoc.apt000066400000000000000000000030271360667575700233050ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - JavaDoc API ------- Jasypt JavaDoc API: Current version These are the API docs for the latest version of jasypt (1.9.3): * jasypt (core) API {{{./api/jasypt/1.9.3/index.html}[Read online]}} * jasypt-hibernate3 API {{{./api/jasypt-hibernate3/1.9.3/index.html}[Read online]}} * jasypt-hibernate4 API {{{./api/jasypt-hibernate4/1.9.3/index.html}[Read online]}} * jasypt-hibernate5 API {{{./api/jasypt-hibernate5/1.9.3/index.html}[Read online]}} * jasypt-spring2 API {{{./api/jasypt-spring2/1.9.3/index.html}[Read online]}} * jasypt-spring3 API {{{./api/jasypt-spring3/1.9.3/index.html}[Read online]}} * jasypt-spring31 API {{{./api/jasypt-spring31/1.9.3/index.html}[Read online]}} * jasypt-spring4 API {{{./api/jasypt-spring4/1.9.3/index.html}[Read online]}} * jasypt-acegisecurity API {{{./api/jasypt-acegisecurity/1.9.3/index.html}[Read online]}} * jasypt-springsecurity2 API {{{./api/jasypt-springsecurity2/1.9.3/index.html}[Read online]}} * jasypt-springsecurity3 API {{{./api/jasypt-springsecurity3/1.9.3/index.html}[Read online]}} * jasypt-springsecurity4 API {{{./api/jasypt-springsecurity4/1.9.3/index.html}[Read online]}} * jasypt-wicket13 API {{{./api/jasypt-wicket13/1.9.3/index.html}[Read online]}} * jasypt-wicket15 API {{{./api/jasypt-wicket15/1.9.3/index.html}[Read online]}} Older versions Jasypt 1.8 * Jasypt API {{{./api/jasypt/1.8/index.html}[Read online]}}jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/jaxb.apt000066400000000000000000000163131360667575700226240ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with JAXB 2.0 ------- Integrating Jasypt with JAXB 2.0 (Mini-Howto) (Mini-Howto contributed by <\311amonn Linehan>) * Introduction The Java Architecture for XML Binding (JAXB) is an API and set of tools in Java for accessing XML through Java. Unlike a SAX or DOM based approach, JAXB does not require any manipulation of XML or knowledge of XML processing libraries. JAXB simply required a developer to bind the schema of an XML document to Java classes (these can be generated). JAXB then look after unmarshalling teh XML document into Java content objects that are available to your program. Wolfgang Laun provides a {{{http://jaxb.java.net/tutorial}comprehensive introduction to JAXB}} at jaxb.java.net. The {{{http://jcp.org/en/jsr/detail?id=222"}JAXB Specification document}} is available from jcp.org. * Step 1: Create an <<>> It is possible to extend JAXB to make it capabable of unmarshalling encrypted XML values to decrypted strings in the corresponding Java objects by creating an 'adapter' class, that extends <<>> and uses Jasypt to do the actual encryption/decryption. Your adapter will be converting between one <<>> and another so the class would look like: ---------- package example.cfg; import java.io.File; import java.io.IOException; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.apache.commons.io.FileUtils; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; public class EncryptedStringXmlAdapter extends XmlAdapter { private final PBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); /** * Constructor. Reads the password from a key file on disk */ public EncryptedStringXmlAdapter() { String keyFile = Environment.getProperty(PropertyConstants.MASTER_KEY_FILE); try { byte[] bytes = FileUtils.readFileToByteArray(new File(keyFile)); String key = new String(bytes); encryptor.setPassword(key); } catch (IOException e) { System.err.println("Could not load key from " + keyFile); } } /** * Encrypts the value to be placed back in XML */ @Override public String marshal(String plaintext) throws Exception { // This encrypts and adds the ENC(...) return PropertyValueEncryptionUtils.encrypt(plaintext, encryptor); } /** * Decrypts the string value */ @Override public String unmarshal(String cyphertext) throws Exception { // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(cyphertext)) return PropertyValueEncryptionUtils.decrypt(cyphertext, encryptor); return cyphertext; } } ---------- The constructor of this class is reading the Jasypt password from a file whose location on disk is specified in a property file. * Step 2: Install your adapter using annotations Here is a simple example of how the adapter might be used to encrypt a configuration file. Imagine your application has an <<>> class with and string fields you want to store encrypted. This class is annotated with JAXB annotations to indicate how it should be mapped to XML. The class will look something like this: ---------- package example.cfg; import java.util.Collections; import java.util.List; import javax.xml.bind.annotation.XmlAccessOrder; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorOrder; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name = "mailserver-config") @XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorOrder(XmlAccessOrder.UNDEFINED) public class EmailConfiguration { @XmlAttribute(required = true) String host; @XmlAttribute(required = true) String port; @XmlElement(required = true) @XmlJavaTypeAdapter(value = EncryptedStringXmlAdapter.class) String username; @XmlElement(required = true) @XmlJavaTypeAdapter(value = EncryptedStringXmlAdapter.class) String password; } ---------- Notice that the @XmlTypeAdapter annotation is added only to the two fields we would like to allow encrypted values in. The above code fragment will map to the following schema: ---------- ---------- * Example: Unmarshalling encrypted configuration from XML using JAXB Using this class an XML configuration file can be created like the one below: --------- mail.example.loc 25 private@example.loc ENC(9Wp+tVgrQSrD71u833wsRxxm96Lq2qoiqkR0jX) --------- Notice that although both of the and fields may contain encrypted values, our adapter implementation will check if the field contains an encrypted value using the <<>> method call. In the example above, only the field contains an encrypted value. This XML fragment can be unmarshalled to a Java object using JAXB with the following code: -------- // JAXB load the mail servers configuration JAXBContext context = JAXBContext.newInstance(EmailConfiguration.class); Unmarshaller unmarshaller = context.createUnmarshaller(); EmailConfiguration configuration = (EmailConfiguration) unmarshaller.unmarshal(ConfigHelper.getConfigStream(EMAIL_CFG_RESOURCE)); -------- This <<>> code is simply a static helper function that opens an <<>> to our XML file on disk and creates an <<>> from which the XML is parsed by JAXB. To test this approach without having to implement a helper function like this one you could store your XML fragment as a <<>> in your class and create a StreamSource from it using: -------- new StreamSource( new StringReader( xmlStr.toString() ) ) -------- When the field of the unmarshalled <<>> object is accessed in code, the decrypted value will be returned. This example has illustrated how any application-specific configuration file can contain encrypted values. Using JAXB 2.0 to load and convert XML to java objects is fast and easy to program. JAXB's extensibility and ability to convert data in XML format to Java objects has allowed us use Jasypt transform from encrypted XML to decrypted strings. Although this example shows one-way (i.e. decryption only) the transformation works in both drections allowing data in any XML document, messaging protocol or RPC mechanism to be protected with Jasypt. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/lite.apt000066400000000000000000000023571360667575700226400ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Using the lite artifact ------- Using the lite artifact Since version 1.7, jasypt includes a lightweight version of the standard jasypt .jar file, in order to reduce the total size in bytes needed in your application to use jasypt. This is especially helpful when using jasypt in mobile platforms. Jasypt "lite" includes both Standard and Pooled, Byte and String digesters and encryptors. And it specifically excludes: * BigDecimal and BigInteger encryption. * The "util" package containing utility classes like <<>> (a correctly configured StandardStringDigester will be used instead). * All Spring/SpringSecurity, Hibernate and Wicket integrations. * Web PBE Configuration artifacts. * CLI utils. * Property file encryption features. * "Zero" salt generator. If you are using Maven, you can easily include the "lite" jar in your application by specifying a : --- org.jasypt jasypt {version} lite compile --- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/maven.apt000066400000000000000000000035031360667575700230030ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Using Jasypt from Apache Maven ------- Using Jasypt from Apache Maven 2.x or 3.x Adding jasypt to your Maven 2 or Maven 3 project is very easy, you just need to add the corresponding dependency to your pom.xml: --------- org.jasypt jasypt {version} compile --------- Alternatively, by specifying a classifier you can use the artifact, which contains only the essentials in a much smaller .jar file. [{{{./lite.html}More Info}}]. --------- org.jasypt jasypt {version} lite compile --------- If you are goint to use any integration modules, just add them in the same way: --------- org.jasypt jasypt-spring31 {version} compile --------- Using Jasypt from Apache Maven 1.x Adding jasypt to your Maven 1.x project is as easy as it is for Maven 2. Maven 1.x does not support transitive dependencies, but anyway jasypt has none (except icu4j if you're using Java 5 or older): --------- org.jasypt jasypt {version} com.ibm.icu icu4j 3.4.4 --------- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/non-default-providers.apt000066400000000000000000000074321360667575700261310ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Using Jasypt with non-default JCE providers ------- If you are looking for advice on using Jasypt with the {{{http://www.bouncycastle.org}Bouncy Castle JCE Provider}}, although this guide will also be relevant for you, you can also have a look at the specific {{{./bouncy-castle.html}Jasypt + Bouncy Castle integration guide}}. Using Jasypt with non-default JCE providers Jasypt has an open JCE provider API which allows the developer to use any existing JCE provider for message digesting or password encryption from jasypt. What this means is that any existing algorithms for both digests or PBE can be used in jasypt, as long as you have a JCE provider which implements it. Note that your Java VM (let's say Sun's) already ships with a JCE provider, which is the one which will be used by jasypt if you do not specify any. * What is a JCE provider? For you as a non-specialised developer, it will be good to know that a JCE provider is just a piece of software which implements encryption algorithms, and which bundles at least one class that implements the <> interface. This class will be the one that we will call "the provider", and one of its methods, <<>> will allow us to know the name with which this provider will be registered at our security framework, if we do so (see below). If we want to use an algorithm shipped with a specific provider from our code, we have three choices: * <>, copying the provider's jar files to the of our JRE installation (<<<$JRE_HOME/lib/ext>>>) and then appending the name of the <<>> class at the end of the provider list at the <<>> file in <<<$JRE_HOME/lib/security>>>. [] * <>, by just calling the <<>> static method in the <<>> class. [] * <>. Some security entities like <<>>s or <<>>s allow you to pass the provider object itself as a parameter when specifying an algorithm. This way the provider doesn't need to be registered previously to its use. * How can you use your own providers in jasypt? Using a non-default JCE provider in jasypt for both message digesting or password-based encryption is really straightforward. You have two options: * <> when configuring your digesters or encryptors, with their <<>> method. Using this method assumes you have already registered a provider with the specified name. [] * <> when configuring your digesters or encryptors, with their <<>> method. The provider doesn't need to be previously registered. Some examples (using the Bouncy Castle provider): ---------------- ... Security.addProvider(new BouncyCastleProvider()); ... StandardPBEStringEncryptor mySecondEncryptor = new StandardPBEStringEncryptor(); mySecondEncryptor.setProviderName("BC"); mySecondEncryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); mySecondEncryptor.setPassword(myPassword); String mySecondEncryptedText = mySecondEncryptor.encrypt(myText); ... ---------------- ---------------- ... StandardStringDigester digester = new StandardStringDigester(); digester.setProvider(new BouncyCastleProvider()); digester.setAlgorithm("WHIRLPOOL"); String digest = digester.digest(message); ... ---------------- jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/seam2.apt000066400000000000000000000144561360667575700227150ustar00rootroot00000000000000 ------- Integrating Jasypt with Seam 2 ------- Integrating Jasypt with Seam 2 (Mini-Howto) (Mini-Howto contributed by ) * Step 1: Adding the dependencies Make sure you include references to Jasypt and its dependencies in your project. Check the {{{./dependencies.html}dependencies page}} for details on the specific jar files to be added. * Step 2: Adding the modules Make Seam aware that you are using Jasypt by adding the following to <<>>: ---------- jasypt-1.9.2.jar icu4j-3.4.4.jar ---------- <>. Either copy them to the server's <<>> directory or make sure they are part of the <<>> file when the app is deployed. If you used <<>> to generate the skeleton for the application then modify the ear target in the <<>> file to include the jars. * Step 3: Use annotations to specify the encrypted fields in your class files The Jasypt {{{./hibernate.html}page on Hibernate 3 integration}} details the steps. Here is a simple example. Imagine you have a <<>> class with an string field you want to store encrypted. The class will look something like this: ---------- package entity.Person; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.GeneratedValue; import javax.persistence.Version; import org.jboss.seam.annotations.Name; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.Parameter; import org.hibernate.validator.Length; import org.jasypt.hibernate3.type.EncryptedStringType; @TypeDef( name="encryptedString", typeClass=EncryptedStringType.class, parameters={@Parameter(name="encryptorRegisteredName", value="myHibernateStringEncryptor")} ) @Entity @Name("person") public class Person implements Serializable { private static final long serialVersionUID = -2082341992912047209L; private Long id; private Integer version; private String firstName; private String lastName; private String ssn; @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Version public Integer getVersion() { return version; } @SuppressWarnings("unused") private void setVersion(Integer version) { this.version = version; } @Length(max=20) public String getFirstName() { return firstName; } public void setFirstName(String name) { this.firstName = name; } public void setLastName(String lastName) { this.lastName = lastName; } public String getLastName() { return lastName; } public void setSsn(String ssn) { this.ssn = ssn; } @Type(type="encryptedString") public String getSsn() { return ssn; } } ---------- Notice that we use simple annotations to define the Hibernate mapping. Also notice the imports you'll need to define in order for this to work. * Step 4: Provide the encryptor to Hibernate This was a problem in earlier version of Seam because there was not an easy way to run code when the application was initialised. Seam 2 solves this problem by providing the <> event. The event fires right after Seam has initialised and started up all components. This provides the perfect place to stick the code that provides the encryptor to Hibernate. To make use of the event, we simply define a class with a method that acts as an observer of the event. Basically, the server is started, right after Seam finishes initializing the event fires, our code gets run. Here is a simple class called <<>> that does the work: ---------- package session; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.EnvironmentPBEConfig; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Observer; import org.jboss.seam.annotations.Logger; import org.jboss.seam.log.Log; @Name("initializer") public class Initializer { @Logger Log log; @Observer("org.jboss.seam.postInitialization") public void initializeJasypt() { log.info("Initializing Jasypt String Encryptor"); StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor(); EnvironmentPBEConfig config = new EnvironmentPBEConfig(); config.setPasswordEnvName("jasypt_password"); strongEncryptor.setConfig(config); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("myHibernateStringEncryptor", strongEncryptor); } } ---------- There are a few things going on here: * First, the encryptor is registered with the name "" <>. That is important for obvious reasons. [] * Second, we are using the <<>> class to configure the encryptor. This is done so that we can specify the password as an environment variable that will be read when the code is run. This might be a better (although optional) solution than leaving the password in a file or hard coded into the app itself because we can immediately unset the variable after the code runs. The <<>> method is used to specify the environment variable that will hold the password, in this case, "". * Step 5: Start the server and test that all is working First set the variable that EnvironmentPBEConfig is expecting: ---------- # export jasypt_password="mysecretpassword" ---------- Start the server in the background so we can get back to the prompt: ---------- # run.sh & ---------- Wait for the server to start up. Look for the logging message indicating that the code actually ran. After the startup is complete, unset the environment variable. ---------- # unset jasypt_password ---------- If all went well then the ssn field will be stored encrypted in the DB! jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/spring.apt000066400000000000000000000006241360667575700232000ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Spring ------- This page has been moved. * {{{./spring2.html}Go to the Spring 2 integration page}}. * {{{./spring3.html}Go to the Spring 3.0 integration page}}. * {{{./spring31.html}Go to the Spring 3.1 integration page}}. * {{{./spring31.html}Go to the Spring 4.0 integration page}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/spring2.apt000066400000000000000000000162101360667575700232600ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Spring 2.x ------- Integrating Jasypt with Spring 2.x Jasypt provides the <<>> artifact for integration with Spring Framework 2.x. Since jasypt 1.9.0, this artifact must be added to your classpath separately. * Using jasypt digesters and encryptors as Spring beans You have nothing special to do register jasypt in Spring, as all of the encryption tools (digesters and encryptors) in jasypt have the adequate design to be correctly instantiated and dependency-injected from a Spring application context. Example: ------------ PBEWithMD5AndTripleDES jasypt ------------ Besides, all digesters and encryptors in jasypt are <>, which means that they can be safely treated as singletons, the default behaviour of Spring's bean container. This avoids concurrency problems in multi-threaded environments like web applications. * Integrating jasypt with Spring's application configuration infrastructure Jasypt provides several Spring-specific configuration management classes: * <<>>, as a totally compatible replacement for Spring's . [] * <<>>, as a totally compatible replacement for Spring's . [] * <<>>: as a totally compatible replacement for Spring's . [] * <<>>: as a totally compatible replacement for Spring's . Their use is analogue to the Spring equivalents, but we can use them to read encrypted property values from our configuration files and apply them to our beans. If we have the properties file seen before (<<>>): --- datasource.driver=com.mysql.jdbc.Driver datasource.url=jdbc:mysql://localhost/reportsdb datasource.username=reportsUser datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) --- We can define in our Spring context configuration: --- /WEB-INF/classes/application.properties ${datasource.driver} ${datasource.url} ${datasource.username} ${datasource.password} --- <<>> and <<>> objects can receive as a constructor argument both an <<>> implementation or an <<>> object. ** Encryptable ServletContextPropertyPlaceholderConfigurer implementation for Spring Jasypt includes <<>>, a subclass of <<>> which allows the transparent decryption of servlet context parameters in web applications (for example, parameters in <<>>). These encrypted parameters can be specified in a way equivalent to that of encrypted parameters in <<<.properties>>> files: --- ... someParameter ENC(...) ... --- ** Encryptable PreferencesPlaceholderConfigurer implementation for Spring Jasypt includes <<>>, a subclass of <<>> which allows the transparent decryption preferences set with JDK 1.4's Preferences API. * Integrating jasypt with Spring Security 2.x For details on how to integrate jasypt with Spring Security 2.x, please have a look at {{{./springsecurity.html}this guide}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/spring3.apt000066400000000000000000000344751360667575700232760ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Spring 3.0 ------- Integrating Jasypt with Spring 3.0 Jasypt provides the <<>> artifact for integration with Spring Framework 3.0. Since jasypt 1.9.0, this artifact must be added to your classpath separately. * {{{Using_jasypt_digesters_and_encryptors_as_Spring_beans}Using jasypt digesters and encryptors as Spring beans}} * {{{Integrating_jasypt_with_Springs_application_configuration_infrastructure}Integrating jasypt with Spring's application configuration infrastructure}} * {{{The_encryption_namespace}The <<>> namespace}} * {{{Integrating_jasypt_with_Spring_Security_3.x}Integrating jasypt with Spring Security 3.x}} * {Using jasypt digesters and encryptors as Spring beans} You have nothing special to do register jasypt in Spring, as all of the encryption tools (digesters and encryptors) in jasypt have the adequate design to be correctly instantiated and dependency-injected from a Spring application context. Example: ------------ PBEWithMD5AndTripleDES jasypt ------------ Besides, all digesters and encryptors in jasypt are <>, which means that they can be safely treated as singletons, the default behaviour of Spring's bean container. This avoids concurrency problems in multi-threaded environments like web applications. * {Integrating jasypt with Spring's application configuration infrastructure} (without using the <<>> namespace) Jasypt provides several Spring-specific configuration management classes: * <<>>, as a totally compatible replacement for Spring's . [] * <<>>, as a totally compatible replacement for Spring's . [] * <<>>: as a totally compatible replacement for Spring's . [] * <<>>: as a totally compatible replacement for Spring's . Their use is analogue to the Spring equivalents, but we can use them to read encrypted property values from our configuration files and apply them to our beans. Note that we can also make use of these integrations using a specific in the Spring XML files called <<>>, which is explained in detail below. If we have the properties file seen before (<<>>): --- datasource.driver=com.mysql.jdbc.Driver datasource.url=jdbc:mysql://localhost/reportsdb datasource.username=reportsUser datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) --- We can define in our Spring context configuration: --- /WEB-INF/classes/application.properties ${datasource.driver} ${datasource.url} ${datasource.username} ${datasource.password} --- <<>> and <<>> objects can receive as a constructor argument both an <<>> implementation or an <<>> object. ** Encryptable ServletContextPropertyPlaceholderConfigurer implementation for Spring Jasypt includes <<>>, a subclass of <<>> which allows the transparent decryption of servlet context parameters in web applications (for example, parameters in <<>>). These encrypted parameters can be specified in a way equivalent to that of encrypted parameters in <<<.properties>>> files: --- ... someParameter ENC(...) ... --- ** Encryptable PreferencesPlaceholderConfigurer implementation for Spring Jasypt includes <<>>, a subclass of <<>> which allows the transparent decryption preferences set with JDK 1.4's Preferences API. * {The <<>> namespace} The <<>> library includes a namespace you can use in your Spring XML files in order to make the declaration of your jasypt entities much easier. This namespace can be included in your XML like this: --- --- Once declared, you will be able to use <<<\>>> tags for: * Creating encryptors and digesters. * Creating configuration beans, both for encryptors and for digesters. * Creating instances of <<>> (extending <<>>) that automatically decrypt entries in <<<.properties>>> files. * Registering an <<>>. ** Creating encryptors and digesters Creating encryptor and digester artifacts with the <<>> namespace is easy. There's a tag for each type of encryptor/digester (including some classes), and each tags is able to specify all of the artifact's properties as tag attributes. Let's see some encryptor declaration examples: --- --- Note how the <<>> parameter will affect the specific implementation of encryptor being created: a <<>> if this parameter is specified, and a <<>> if not. Now for some digesters: --- --- Again, the <<>> attribute will determine whether the digesters will be or . Some artifacts can also be instantiated this way: --- --- ** Creating configuration beans for encryptors and digesters Configuration beans implement the <<>> interface for digesters and <<>> for encryptors, and Jasypt offers several implementations of these interfaces out-of-the-box depending on whether the digester to be created is meant for bytes or Strings, and also whether some configuration parameters can come from environment variables and/or system properties. The <<>> namespace will automatically choose the correct config bean implementation to be instantiated depending on the specified configuration attributes, so that you do not have to worry about the specific implementation class you need. Let's see some examples: --- --- Using these beans in our encryptors/digesters is easy: --- --- ** Creating EncryptableProperties instances Usually, in Spring you can create a <<>> bean in your XML using the <<>> namespace, like this: --- --- Jasypt allows you to register an <<>> object in an equivalent manner, simply by adding an bean reference: --- --- This <<<\>>> tag works in exactly the same way and with exactly the same features as <<<\>>>, and as the object it registers is a subclass of <<>>, you can autowire it inside your application with your code not even noticing these properties are originally encrypted. ** Registering an EncryptablePropertyPlaceholder/Override Spring allows you to easily register a <<>> that takes care of the resolution of your <<<$\{...\}>>> property expressions: --- --- But if you want to register an <<>> instead because your property files might be encrypted, you can do: --- --- And that's it! A property override implementation is also provided: --- --- * {Integrating jasypt with Spring Security 3.x} For details on how to integrate jasypt with Spring Security 3.x, please have a look at {{{./springsecurity.html}this guide}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/spring31.apt000066400000000000000000000362211360667575700233460ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Spring 3.1 and Spring 4.0 ------- Integrating Jasypt with Spring 3.1 and Spring 4.0 Jasypt provides the <<>> and <<>> artifacts for integration with Spring Framework 3.1 and Spring Framework 4.0. Since jasypt 1.9.0, this artifact must be added to your classpath separately. For those migrating from Spring 3.0, Jasypt's support for Spring 3.1 is basically the same as that for Spring 3.0, adding an encryption-aware implementation for the new <<>> interface and removing support for the deprecated <<>>. Also, if you were using the <<>> namespace with Spring 3.0 and migrate your app to Spring 3.1, be sure to change the XSD definition in order to point to the Spring 3.1-specific version (see below). * {{{Using_jasypt_digesters_and_encryptors_as_Spring_beans}Using jasypt digesters and encryptors as Spring beans}} * {{{Encryptable_PropertySource_implementation_for_Spring_3.1}Encryptable PropertySource implementation for Spring 3.1 and Spring 4.0}} * {{{Integrating_jasypt_with_Springs_application_configuration_infrastructure}Integrating jasypt with Spring's application configuration infrastructure}} * {{{The_encryption_namespace}The <<>> namespace}} * {{{Integrating_jasypt_with_Spring_Security_3.x}Integrating jasypt with Spring Security 3.x and Spring Security 4.x}} * {Using jasypt digesters and encryptors as Spring beans} You have nothing special to do register jasypt in Spring, as all of the encryption tools (digesters and encryptors) in jasypt have the adequate design to be correctly instantiated and dependency-injected from a Spring application context. Example: ------------ PBEWithMD5AndTripleDES jasypt ------------ Besides, all digesters and encryptors in jasypt are <>, which means that they can be safely treated as singletons, the default behaviour of Spring's bean container. This avoids concurrency problems in multi-threaded environments like web applications. * {Encryptable PropertySource implementation for Spring 3.1 and Spring 4.0} Jasypt includes <<>>, an implementation of <<>> which allows integrating jasypt encryption with Spring 3.1 and Spring 4.0's configuration infrastructure. You can use it as you would with any other PropertySource: --- EncryptablePropertiesPropertySource encPropSource = new EncryptablePropertiesPropertySource("encProps", properties, encryptor); ... ApplicationContext ctx = ... MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); sources.addFirst(encPropSource); --- See the {{{./javadoc.html}JavaDoc API}} for <<>> for more detail. * {Integrating jasypt with Spring's application configuration infrastructure} (without using the <<>> namespace) Besides the <<>> implementation already explained, Jasypt provides several Spring-specific configuration management classes: * <<>>, a totally compatible replacement for Spring's . [] * <<>>, a totally compatible replacement for Spring's . [] * <<>>: a totally compatible replacement for Spring's . Their use is analogue to the Spring equivalents, but we can use them to read encrypted property values from our configuration files and apply them to our beans. Note that we can also make use of these integrations using a specific in the Spring XML files called <<>>, which is explained in detail below. If we have the properties file seen before (<<>>): --- datasource.driver=com.mysql.jdbc.Driver datasource.url=jdbc:mysql://localhost/reportsdb datasource.username=reportsUser datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) --- We can define in our Spring context configuration: --- /WEB-INF/classes/application.properties ${datasource.driver} ${datasource.url} ${datasource.username} ${datasource.password} --- <<>> and <<>> objects can receive as a constructor argument both an <<>> implementation or an <<>> object. ** Encryptable PreferencesPlaceholderConfigurer implementation for Spring Jasypt includes <<>>, a subclass of <<>> which allows the transparent decryption preferences set with JDK 1.4's Preferences API. * {The <<>> namespace} The <<>> and <<>> libraries includes a namespace you can use in your Spring XML files in order to make the declaration of your jasypt entities much easier. This namespace can be included in your XML like this: --- --- Once declared, you will be able to use <<<\>>> tags for: * Creating encryptors and digesters. * Creating configuration beans, both for encryptors and for digesters. * Creating instances of <<>> (extending <<>>) that automatically decrypt entries in <<<.properties>>> files. * Registering an <<>>. ** Creating encryptors and digesters Creating encryptor and digester artifacts with the <<>> namespace is easy. There's a tag for each type of encryptor/digester (including some classes), and each tags is able to specify all of the artifact's properties as tag attributes. Let's see some encryptor declaration examples: --- --- Note how the <<>> parameter will affect the specific implementation of encryptor being created: a <<>> if this parameter is specified, and a <<>> if not. Now for some digesters: --- --- Again, the <<>> attribute will determine whether the digesters will be or . Some artifacts can also be instantiated this way: --- --- ** Creating configuration beans for encryptors and digesters Configuration beans implement the <<>> interface for digesters and <<>> for encryptors, and Jasypt offers several implementations of these interfaces out-of-the-box depending on whether the digester to be created is meant for bytes or Strings, and also whether some configuration parameters can come from environment variables and/or system properties. The <<>> namespace will automatically choose the correct config bean implementation to be instantiated depending on the specified configuration attributes, so that you do not have to worry about the specific implementation class you need. Let's see some examples: --- --- Using these beans in our encryptors/digesters is easy: --- --- ** Creating EncryptableProperties instances Usually, in Spring you can create a <<>> bean in your XML using the <<>> namespace, like this: --- --- Jasypt allows you to register an <<>> object in an equivalent manner, simply by adding an bean reference: --- --- This <<<\>>> tag works in exactly the same way and with exactly the same features as <<<\>>>, and as the object it registers is a subclass of <<>>, you can autowire it inside your application with your code not even noticing these properties are originally encrypted. ** Registering an EncryptablePropertyPlaceholder/Override Spring allows you to easily register a <<>> that takes care of the resolution of your <<<$\{...\}>>> property expressions: --- --- But if you want to register an <<>> instead because your property files might be encrypted, you can do: --- --- And that's it! A property override implementation is also provided: --- --- * {Integrating jasypt with Spring Security 3.x and Spring Security 4.x} For details on how to integrate jasypt with Spring Security 3.x, and Spring Security 4.x please have a look at {{{./springsecurity.html}this guide}}. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/springsecurity.apt000066400000000000000000000271261360667575700247760ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Spring Security (and older Acegi Security) ------- If you want to know what jasypt can do to improve the security of your users' passwords in an acegi-enabled application, check the {{{./faq.html}FAQ}} and also the article '{{{./howtoencryptuserpasswords.html}How to encrypt user passwords}}' guide. Integrating Jasypt with Spring Security 2.x, 3.x or 4.x (or Acegi 1.x) Jasypt provides the <<>>, <<>>, <<>> and <<>> artifacts for integration with Spring Security 1.x, 2.x, 3.x and 4.x. Since jasypt 1.9.0, these artifacts must be added to your classpath separately. These integration libraries allow the integration of jasypt's powerful password encryption capabilities into Spring Security-enabled applications. Once integrated, jasypt will be responsible for managing the check of users' passwords at sign in in a transparent way for the rest of the security framework. Password encryption is set up in Spring Security by injecting an object implementing the <<>> (ACEGI 1.x), <<>> (Spring Security 2.x), <> (Spring Security 3.x) or <> (Spring Security 4.x) interface into your <<>>. Jasypt provides two implementations of this <<>> interface for each of ACEGI 1.x and Spring Security 2.x, 3.x and 4.x: * <> / <> / <> / <>, which is used for uni-directional password encryption (recommended), and which can wrap either an <> or an <> object. [] * <> / <> / < / <>, which is used for bi-directional password encryption (not recommended), and which can wrap either an <> or an <> object. Please note that , but bi-directional password encryption (this is, passwords which can be decrypted) is allowed in order to support some legacy and complex inter-application integration scenarios. Also, jasypt includes org.jasypt.springsecurity3|springsecurity4|.TokenBasedRememberMeServices for Spring Security 3 and Spring Security 4, which works in the same way as org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices but creating a jasypt-digested data signature for inclusion in rememeber-me cookies. * org.jasypt.acegisecurity|springsecurity2|springsecurity3|springsecurity4.crypto.password|.PasswordEncoder These <<>> implementations can wrap either an <> implementation (<<>>, <<>>, <<>>,...) or an <> implementation (<<>>,...). This means that all uni-directional encryption methods supported in jasypt can be integrated into ACEGI / Spring Security using this adapter. It can be used from your Spring XML resource files like this (for a <<>> and Spring Security 3.x): ------------ ... ... ... ... ... ... ------------ Or like this (for a <<>> and Spring Security 3.x): ------------ ... ... ... ... ... ... ------------ * org.jasypt.acegisecurity|springsecurity2|springsecurity3|springsecurity4.crypto.password|.PBEPasswordEncoder These <<>> implementations can wrap either an <> implementation (<<>>, <<>>,...) or an <> implementation (<<>>,...). This means that all bi-directional encryption methods supported in jasypt can be integrated into ACEGI / Spring Security using this adapter. It can be used from your Spring XML resource files like this (for a <<>> and Spring Security 3.x): ------------ ... ... ... ... ... ... ------------ Or like this (for a <<>> and Spring Security 3.x): ------------ ... ... ... ... ... ... ------------ * Using other JCE providers like Bouncy Castle With Jasypt, you can easily integrate the {{{http://www.bouncycastle.org}Bouncy Castle}} JCE provider (or any other JCE provider) into your Acegi / Spring Security infrastructure, thus being able to use lots of new algorithms for password encryption at your apps. For example, you could use the hash function on your passwords just like this: ------------ ... ... ... WHIRLPOOL ... ... ... ... ... ------------ jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/tapestry.apt000066400000000000000000000006621360667575700235530ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Tapestry ------- Integrating Jasypt with Tapestry There is an external article regarding integration of Jaspt with Tapestry: {{{http://tawus.wordpress.com/2011/05/06/tapestry-magic-11-integration-with-jasypt-for-encrypting-urls/}Tapestry Magic #11: Integration with Jasypt for encrypting URLs}} Author: {{{http://tawus.wordpress.com/}tawus}} jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/team.apt000066400000000000000000000113511360667575700226230ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Team ------- Development Team The team is comprised of Members and Contributors. Members have direct access to the source of a project and actively evolve the code-base. Contributors improve the project through submission of patches and suggestions to the Members. The number of Contributors to the project is unbounded. Get involved today. All contributions to the project are greatly appreciated. * Members *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ | <> | <> | <> | <> | <> | *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ |chuspicosvilar |Chus Picos | Spain | chuspicosvilar AT users.sourceforge.net | Project Co-lead | *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ |hokitorres |Hoki Torres | Spain | hokitorres AT users.sourceforge.net | Project Co-lead | *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ * Former Members *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ | <> | <> | <> | <> | <> | *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ |dfernandez |Daniel Fernndez | Spain | https://github.com/danielfernandez | Original author | *-----------+--------------------------------+---------------------+--------------------------------------+----------------------------------+ * Contributors *--------------------------------+-------------------------------------+----------------------------------+ | <> | <> | <> | *--------------------------------+-------------------------------------+----------------------------------+ |Ivn Garca Sinz-Aja | Spain | ivangsa AT users.sourceforge.net | *--------------------------------+-------------------------------------+----------------------------------+ |Steven Coco | U.S.A. | hello AT stevencoco.com | *--------------------------------+-------------------------------------+----------------------------------+ |Marcos Muo Garca | Spain | bardaos AT gmail.com | *--------------------------------+-------------------------------------+----------------------------------+ |Grgory Joseph | Switzerland | greg.jos AT gmail.com | *--------------------------------+-------------------------------------+----------------------------------+ |Frank Mena | U.S.A. | frankm.os AT gmail.com | *--------------------------------+-------------------------------------+----------------------------------+ |Carlos Fernndez | U.S.A. | carlosft1 AT users.sourceforge.net| *--------------------------------+-------------------------------------+----------------------------------+ |amonn Linehan | Ireland | eamonnlinehan AT gmail.com | *--------------------------------+-------------------------------------+----------------------------------+ |Patrick J. Maloney | U.S.A. | patrickjmaloney AT users.sourceforge.net | *--------------------------------+-------------------------------------+----------------------------------+ |Soraya Snchez | Spain | sschz AT users.sourceforge.net | *--------------------------------+-------------------------------------+----------------------------------+ |Suresh Jaganathan | United Kingdom | sureshnath AT users.sf.net | *--------------------------------+-------------------------------------+----------------------------------+ |Eamonn Dunne | Ireland | eamonn.dunne AT gmail.com | *--------------------------------+-------------------------------------+----------------------------------+ jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/webconfiguration.apt000066400000000000000000000134771360667575700252550ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Web PBE Configuration ------- Web PBE Configuration When in a web application, Jasypt allows developers to avoid storing encryption passwords for PBE encryptors in files inside the webapp, specifying instead these passwords to the application through a web interface each time it is deployed. This is achieved thanks to an infrastructure consisting of: * <>: <<>> and <<>>, which when assigned to an encryptor, "mark" this encryptor as eligible for receiving its password via web. [] * A <>, <<>> which will let us create our encryptors, set them their <<>> configs and register them somewhere in our application. This context listener will be unnecessary if we are using the Spring Framework. [] * A <>, <<>>, which will avoid any user to access the web application until the encryption passwords have been set by the admin. [] * A <>, <<>>, which will show the authorised user a form with which he/she can set the encryption passwods for all encryptors with a <<>>. * WebPBEConfig For an encryptor to be assigned a password from the web, it only has to be assigned a WebPBEConfig object, which must be initialised with a unique name an a validation word. The name will identify the config object (and thus the encryptor) and the validation word will make sure that only an authorised person (for example, the application deployer) sets the passwords. * WebPBEInitializationContextListener This is a ContextListener which takes an <<>> implementation class name as a parameter (context-param) and calls its <<>> method to allow the webapp to create its PBE encryptors and declare their associated <<>> objects. An example <<>> implementation: ------- package myapp; ... public class MyWebPBEInitializer implements WebPBEInitializer { public void initializeWebPBEConfigs() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); WebPBEConfig webConfig = new WebPBEConfig(); webConfig.setValidationWord("jasypt"); webConfig.setName("Main Password"); encryptor.setConfig(webConfig); // Get some user-defined singleton or similar, and register // the encryptor with it so that it can be accessed from the // rest of the application. } } ------- An example <<>> fragment, registering the context listener: ------- webPBEInitializerClassName myapp.MyWebPBEInitializer org.jasypt.web.pbeconfig.WebPBEInitializationContextListener ------- <>: If the web application uses <>, <<>> objects are declared as beans in the Spring context and this Spring context is initialised at application deploy time (with Spring's <<>>), the use of this context listener will become unnecessary. * WebPBEConfigFilter This filter is intended to avoid access to the web application until an admin has set the encryption passwords. It will query the web PBE config system to know whether passwords have been set and, if not, it will show the user a plain page. An example <<>> fragment (being applied on a Struts servlet): ------- webPBEConfigFilter org.jasypt.web.pbeconfig.WebPBEConfigFilter webPBEConfigFilter strutsActionServlet ------- * WebPBEConfigServlet This servlet's URL should be called by the webapp administrator at deploy time, for setting the passwords of all the PBE encryptors which have been previously assigned a <<>> configuration object. If web PBE configuration has not been done yet, it will show the user a form containing two inputs for each encryptor: the and the (retyped). * The must be input to the value set on the <<>> object with its <<>> method. This will ensure that only an authorised person will set the encryption passwords. * The (retyped) must be input to the value which is desired to be the encryption password for each specific encryptor. [] [images/webConfig.png] Web PBE configuration form An example <<>> fragment: ------- webPBEConfigServlet org.jasypt.web.pbeconfig.WebPBEConfigServlet 1 webPBEConfigServlet /webPBEConfig.do ------- If this servlet's context is set a logger, it will output messages for both successful and failed attempts to set passwords, including date, time and originating IP address. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/whatsnew17.apt000066400000000000000000000224661360667575700237160ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - What is new in Jasypt 1.7 ------- <> What is new in Jasypt 1.7 * Hibernate 3.6 compatibility Hibernate 3.6.0.Final introduced some changes to its custom type API which made jasypt transparent encryption types produce exceptions during initialization. This issue has been fixed while keeping backwards compatibility with older 3.x versions of Hibernate. * Removal of third-party dependencies Dependencies on both the Apache Commons-Lang and Apache Commons-Codec libraries have been removed. All you need now to run jasypt is: * <<>> if you are using Java version 6 or newer. * <<>> and <<>> if you are using Java version 5 or older. * Improved performance in multi-processor/multi-core systems Jasypt 1.7 includes pool-based versions of Standard(Byte|String)Digester and StandardPBE(Byte|String|BigDecimal|BigInteger)Encryptor which can vastly improve performance in multi-processor/multi-core systems. These pooled digesters and encryptors have exactly the same API as their non-pooled "Standard" relatives --so they can be used interchangeably-- but add a new configuration parameter called "poolSize" which establishes the amount of Standard* digesters/encryptors they will internally hold. --- PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); encryptor.setAlgorithm(algorithm); encryptor.setPassword(encPassword); ... final String result = encryptor.encrypt(message); ... --- These pooled objects will use their internal Standard* digesters/encryptors to serve the requests in round-robin, so the amount of thread blocking caused by the synchronised code in the Standard* artifacts is reduced to a minimum. These implementations do not create new threads, so they can be safely used in container-controlled environments which do not allow the creation of new threads. The pool size recommended for a specific application and machine depends on many factors, but will be approximately equal to the number of processors/cores in the machine. * Lightweight jar Jasypt 1.7 includes a version of the standard jasypt .jar file, in order to reduce the total size in bytes needed in your application to use jasypt. This is especially helpful when using jasypt in mobile platforms. Jasypt "lite" includes both Standard and Pooled, Byte and String digesters and encryptors. And it specifically excludes: * BigDecimal and BigInteger encryption. * The "util" package containing utility classes like <<>> (a correctly configured StandardStringDigester will be used instead). * All Spring, Hibernate and Wicket integrations. * Web PBE Configuration artifacts. * CLI utils. * Property file encryptions. * "Zero" salt generator. If you are using Maven, you can easily include the "lite" jar in your application by specifying a : --- org.jasypt jasypt 1.7 lite compile --- * Algorithm Registry Jasypt 1.7 adds a class called <<>> aimed at easily listing the digest and PBE encryption algorithms currently present in your system (and usable by jasypt). It is very simple to use: --- // digestAlgos is a Set containing the names of the algorithms Set digestAlgos = AlgorithmRegistry.getAllDigestAlgorithms(); ... --- Also, a new command line utility script has been added to the <<>> folder of the jasypt distribution that will list your jasypt-ready algorithms from the command line: --- $ cd jasypt-1.7/bin $ ./listAlgorithms.sh DIGEST ALGORITHMS: [MD2, MD5, SHA, SHA-256, SHA-384, SHA-512] PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40] --- * Prefix and Suffix New "<<>>" and "<<>>" configuration parameters have been added to String digesters that allow the specification of a prefix and/or a suffix that will be added to the digest results, and also expected when matching existing digests. * Lenient salt size checking A new configuration parameter has been added to digesters in order to enable a lenient behaviour towards salt size in digests when checking them. This allows a digester to check as valid a digest created with a different amount of salt bytes than the value currently configured for it with <<>>. * Salt positioning New configuration parameters have been added to digesters in order to invert the position of the salt bytes in relation to the message being digested before and after the digest operation. The "<<>>" configuration parameter allows salt to be positioned after the message being digested (instead of the default, which is before) before applying the digest function to the whole. The "<<>>" configuration parameter allows plain (non-digested) salt to be positioned after the results of the digest operation (instead of the default, which is before) after the digest function has been applied. Both these configuration parameters allow compatibility with some encryption schemes which require the salt bytes to be positioned after the message, like for example most implementations of the SSHA password encyption scheme defined in RFC2307: --- final StandardStringDigester ssha = new StandardStringDigester(); ssha.setAlgorithm("SHA-1"); ssha.setIterations(1); ssha.setSaltSizeBytes(8); ssha.setPrefix("{SSHA}"); ssha.setInvertPositionOfSaltInMessageBeforeDigesting(true); ssha.setInvertPositionOfPlainSaltInEncryptionResults(true); ssha.setUseLenientSaltSizeCheck(true); ... // This result will change each time it is executed due to random salt: // result == "{SSHA}agbpAYBa95UqQml810zUv0c8aNUUcWdtH5u8Yw==" final String result = ssha.digest --- * Compatibility with RFC2307 password encryption standards used in LDAP systems Thanks to the new configuration parameters added to jasypt, a new "util" package has been created in <<>> containing utility classes for password checking following the schemes defined in RFC2307 (especially common in LDAP systems): * RFC2307SHAPasswordEncryptor: SHA-1 algorithm, no salt, no iterations. * RFC2307MD5PasswordEncryptor: MD5 algorithm, no salt, no iterations. * RFC2307SSHAPasswordEncryptor: SHA-1 algorithm, 8-byte salt (configurable), salt positioned after message, lenient salt size checking, no iterations. * RFC2307SMD5PasswordEncryptor: MD5 algorithm, 8-byte salt (configurable), salt positioned after message, lenient salt size checking, no iterations. * Rebuilt command-line (CLI) scripts The command-line scripts included in the <<>> folder of the jasypt distribution package have been rewritten in order to add the new configuration parameters and also fix problems that didn't allow these scripts to be correctly executed from outside the folder that contained them. * Rebuilt zip distribution package The jasypt zip distribution package has been reconfigured and rebuilt in order to remove the now-unnecessary "cli-bundle" jar file and to add icu4j to the <<>> folder so that users with Java version < 6 do not have to add it themselves to the <<>> environment variable to use the command line utils. * Encryptable ServletContextPropertyPlaceholderConfigurer implementation for Spring Jasypt 1.7 includes <<>>, a subclass of <<>> which allows the transparent decryption of servlet context parameters in web applications (for example, parameters in <<>>). These encrypted parameters can be specified in a way equivalent to that of encrypted parameters in <<<.properties>>> files: --- ... someParameter ENC(...) ... --- * Encryptable PreferencesPlaceholderConfigurer implementation for Spring Jasypt 1.7 includes <<>>, a subclass of <<>> which allows the transparent decryption preferences set with JDK 1.4's Preferences API. * TokenBasedRememberMeServices implementation for Spring Security 3 Jasypt 1.7 includes <<>> for Spring Security 3, which works in the same way as <<>> but creating a jasypt-digested data signature for inclusion in rememeber-me cookies. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/whatsnew19.apt000066400000000000000000000122701360667575700237100ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - What is new in Jasypt 1.9 ------- What is new in Jasypt 1.9? * {{{Modularization}Modularization}} * {{{Hibernate_4_support}Hibernate 4.0 and Hibernate 5.0 support}} * {{{Enhanced_Spring_3.0_support}Enhanced Spring 3.0 support}} * {{{Spring_3.1_support}Spring 3.1 and Spring 4.0 support}} * {{{Spring_Security_4.0_support}Spring Security 4.0 support}} * {{{Apache_Wicket_1.5_support}Apache Wicket 1.5 support}} * {{{Minor_bugs_and_testing_enhancements}Minor bugs and testing enhancements}} * {Modularization} Since version 1.9.0, jasypt will offer a and several separate integration modules instead of a single artifact containing them all. This will allow a better integration between jasypt and the different versions of the supported technologies (Hibernate, Spring, etc.) The new modules are: * <<>> (core) * Spring integration * <<>> for Spring Framework 2.0 and 2.5 * <<>> for Spring Framework 3.0 * <<>> for Spring Framework 3.1 * <<>> for Spring Framework 4.0 and newer * <<>> for Acegi Security 1.0 * <<>> for Spring Security 2.x * <<>> for Spring Security 3.x * <<>> for Spring Security 4.x and newer * Hibernate integration * <<>> for Hibernate 3.0, 3.1, 3.2, 3.3, 3.5 and 3.6 * <<>> for Hibernate 4.x * <<>> for Hibernate 5.x and newer * Apache Wicket integration * <<>> for Apache Wicket 1.3 and 1.4 * <<>> for Apache Wicket 1.5 * {Hibernate 4.0 and Hibernate 5.0 support} Jasypt 1.9 adds support for Hibernate 4 and Hibernate 5 by creating specific <<>> and <<>> modules. Features offered are the same as for Hibernate 3, but adapted to the new specific APIs of this new Hibernate major version. Learn more at the {{{./hibernate.html}Jasypt + Hibernate Guide}}. * {Enhanced Spring 3.0 support} Jasypt 1.9 adds to its existing Spring 3.0 support an XML namespace called <<>>, which allows creating many jasypt artifacts as easily as: --- --- ...even when using complex environment-based configurations: --- --- The same goes for digesters / digester utils: --- --- Also, encryptable .properties files (<<<.properties>>> files which include encrypted entries that are transparently decrypted) can be easily created in a way equivalent to Spring's <<<\>>>: --- --- And an <<>> can be declared in a way equivalent to Spring's <<<\>>>, so that encrypted entries in <<<.properties>>> files can be resolved with <<<$\{...\}>>>: --- --- Learn more at the {{{./spring3.html}Jasypt + Spring 3.0 Guide}}. * {Spring 3.1 and Spring 4.0 support} Jasypt 1.9 features for Spring 3.1 and Spring 4.0 are equivalent to those for Spring 3.0 --excluding those that were deprecated--. The new <<>> namespace is also offered in Spring 3.1 and Spring 4.0. Besides, jasypt provides an <<>> implementation of the new <<>> interface for , and adapts the behaviour of its <<<\>>> to that of Spring 3.1 and Spring 4.0, which bases <<<$\{...\}>>> property resolution on querying the registered . Learn more at the {{{./spring31.html}Jasypt + Spring 3.1 and Spring 4.0 Guide}}. * {Spring Security 4.0 support} Jasypt 1.9 adds support for Spring Security 4.0 by creating a new specific <<>> module. Features offered are the same as for Spring Security 3, but adapted to the new specific APIs of this new Hibernate major version. Learn more at the {{{./springsecurity.html}Jasypt + Spring Security Guide}}. * {Apache Wicket 1.5 support} jasypt 1.9 adds specific support for Apache Wicket 1.5, due to some changes in its encryption APIs since 1.4. Learn more at the {{{./wicket.html}Jasypt + Apache Wicket Guide}}. * {Minor bugs and testing enhancements} Some minor bugs have already been fixed, and the project's unit-testing infrastructure has been significantly improved. jasypt-jasypt-1.9.3/jasypt-dist/src/site/apt/wicket.apt000066400000000000000000000077051360667575700231730ustar00rootroot00000000000000 ------- Jasypt: Java simplified encryption - Integrating Jasypt with Apache Wicket ------- Integrating Jasypt with Apache Wicket Jasypt provides the <<>> (for Wicket 1.3 and 1.4) and <<>> (for Wicket 1.5) artifacts for integration with Apache Wicket. Since jasypt 1.9.0, these artifacts must be added to your classpath separately. Although the most usual way of using jasypt in wicket applications is password encryption, transparent data persistance, etc. as usual, and for these operations no especial wicket integration features are needed, there still exist some specific security features in wicket which could make a good use of an encryption library like Jasypt. Specifically, . Wicket can configure URLs to be encrypted, like <<>>. And for supporting this feature, it provides two cryptography utility interfaces called <<>> (for encryptor factories) and <<>> (for encryptor objects). Wicket provides a set of simplistic implementations of these interfaces, but security and configurability can be vastly improved by using jasypt's infrastructure. Jasypt provides: * <>, an implementation of wicket's <<>> interface which receives an <<>> object (configured at the user's wish: environment variables, web PBE config...) and provides encryptors of class <<>> (implementing <<>> interface). [] * <>, implementation of wicket's <<>> returned by <<>>. Note that <<>> objects adhere to wicket specifications of returning String output in the form of . * Configuring the factory The ICryptFactory being used is configured at the <<>> method of the class. --- public class MyApplication extends WebApplication { ... ... @Override protected void init() { super.init(); /* * In the following code example we will create a Jasypt byte * encryptor by hand, but in real world we can get it from Spring, * configure it via Web PBE configuration... whatever we want to. */ StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); encryptor.setPassword("jasypt"); StringFixedSaltGenerator generator = new StringFixedSaltGenerator("wicketwicketwicketwicketwicket"); encryptor.setSaltGenerator(generator); /* * Create the Jasypt Crypt Factory with the desired encryptor, * which will return org.jasypt.wicket.JasyptCrypt objects implementing * the org.apache.wicket.util.crypt.ICrypt interface. */ ICryptFactory jasyptCryptFactory = new JasyptCryptFactory(encryptor); /* * Set the Jasypt Crypt Factory into the application configuration. */ getSecuritySettings().setCryptFactory(jasyptCryptFactory); } ... ... } --- * Configuring URL encryption Finally, for configuring URL encryption for our application: --- public class MyApplication extends WebApplication { ... ... @Override protected IRequestCycleProcessor newRequestCycleProcessor() { return new WebRequestCycleProcessor() { @Override protected IRequestCodingStrategy newRequestCodingStrategy() { return new CryptedUrlWebRequestCodingStrategy(new WebRequestCodingStrategy()); } }; } ... ... } ---jasypt-jasypt-1.9.3/jasypt-dist/src/site/fml/000077500000000000000000000000001360667575700211605ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/fml/faq.fml000066400000000000000000000734721360667575700224440ustar00rootroot00000000000000 About Jasypt Where does Jasypt come from? Is it made or backed by any software company?

Jasypt is Open Source Software created in his spare time by a Spanish Software Engineer called Daniel Fernndez --also author of other popular java libraries like thymeleaf or op4j--, and which has also received contributions of diverse kind from some other people.

It is neither made nor backed by any software (or any other type of) company, and it is offered to the public totally free of charge, both in binary and in source code forms, under the Apache License 2.0.

Does it implement or include any cryptographic algorithms?

No, it doesn't, Jasypt by itself does not implement nor distribute in any of its forms any cryptographic algorithms. It simply uses the algorithms already present in the users' Java installations via the Java Cryptography Extension.

Is it stable? Can it be considered production-ready?

Yes, it can be considered stable and production-ready.

Does Jasypt offer any type of commercial support or warranty?

No, it does not. Commercial support is not offered at the moment.

Also, jasypt is offered without warranties of any kind, as expressed in the Apache 2.0 License.

How can I contribute to Jasypt?

In many ways:

  • You can write to the Team with your ideas for improving Jasypt.
  • You can contribute some code, write a patch for a new feature or behaviour (please, tell the project admins first about your idea so that effort can be correctly coordinated).
  • You can write articles, reviews, blog posts, etc. about Jasypt, showing how it works or how it integrates with other technologies.
  • You can promote Jasypt in your company/work, showing your colleagues or customers how encryption can be an easy and powerful task by using Jasypt.

If you want to contribute some code to Jasypt, please read first the page on Contributing to Jasypt.

What is Jasypt's export classification in the United States of America?

Although Jasypt does not implement nor distribute in any of its forms any cryptographic algorithms, it can use them via the Java Cryptography Extension API and, as such, it is classified under ECCN code 5D002 and approved for export under License Exception TSU.

General What is jasypt useful for? Give me some examples of use, please...

Jasypt is useful for many encryption tasks associated with applications, for example:

  • Encrypting (digesting) passwords.
  • Encrypting sensitive information.
  • Encrypting data communications.
  • Creating sums for integrity checking of data.
  • ...and many more.
Is it "simplified encryption" because it is less safe?

No. Jasypt does not implement any encryption algorithms, but instead delegates to the ones already provided by a JCE (Java Cryptography Extension) provider, which can be either the default VM one or any other of your choice, adding a layer for ease and correctness of use, configurability, integration with many other technologies, etc.

It is "simplified encryption" because it is much easier to use and integrate than the standard APIs, but you will get the same encryption power as if you were using the JCE API directly, or even more, as jasypt will enforce best practices and use standards that will ensure that you always get the highest level of security from the encryption features present in your Java installation.

Is jasypt intended for use only in web applications?

No, not at all. Jasypt offers some special configuration facilities to web applications, but it is not necessary for an application to be web-based in order to use jasypt. Jasypt will not add any dependency on any web-related API to your application if you don't want it to.

I don't use Hibernate at all. Can I use jasypt anyway?

Yes, you can. Jasypt provides an optional integration package for Hibernate, but it does not need Hibernate for normal operation. It won't add a dependency on Hibernate to your project.

I don't use Spring at all. Can I use jasypt anyway?

Yes, you can. Jasypt is designed to be seamlessly integrated into a Spring-based application if required, but it does not depend on Spring in any way. It won't add a dependency on Spring to your project nor will force you to develop in an IoC-friendly manner.

I don't use Spring Security (or Acegi) at all. Can I use jasypt anyway?

Yes, you can. Jasypt provides an optional integration package for Spring Security, but it does not need Spring Security for normal operation.It won't add a dependency on Spring Security to your project.

Can jasypt use the Bouncy Castle JCE provider? Is it required?

Yes, since version 1.3, it can. The provider API in jasypt is open, so that you can use Bouncy Castle or any other JCE provider of your choice. You will only have to specify your provider to the encryptors or digesters you are using when configurig them.

But, Bouncy Castle is not required. Jasypt has no dependency on it, and thus you can decide not to use Bouncy Castle at all, for example if you want to use the algorithms shipped with your JVM's JCE default provider.

Are algorithms like AES or WHIRLPOOL supported in jasypt?

Yes and no. Jasypt by itself does not implement any algorithms, but it lets you use any JCE provider of your choice.

AES (encryption) is supported by the Sun JCE provider since Java 8, and it can be used by Jasypt since version 1.9.3.

Also, both AES (encryption) and WHIRLPOOL (digests) are algorithms supported by the Bouncy Castle JCE provider, and thus you can use them from jasypt as long as you set Bouncy Castle as your JCE provider for your jasypt encryptors or digesters.

Which is the difference between digests and password-based encryption?

Digests are the results of applying cryptographic hash functions such as MD5, and are a type of one-way encryption. This means that an original input cannot be reconstructed from its digest, once it has been generated.

Password-based encryption is a type of bidirectional encryption, which means that encrypted data can be decypted to reconstruct the original input. Encryption is done by generating an encryption key, and passing it to an encryption algorithm such as DES. This key, in password-based encryption, is derived from a password set by the user (usually by a applying a digest algorithm to it).

How can I use a SNAPSHOT release of Jasypt?

From time to time, Jasypt will produce a snapshot release that will allow you to test new or being-developed features. These are non production ready releases, but will be stable enough for most testing purposes, and will enable you to try new features before they are generally available.

In order to use snapshot releases, you need to add the Sonatype OSS Snapshots repository in your Maven pom.xml file, like this (the dots are only for indenting, remove them in your code):

<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

Also, you will have to modify your Jasypt dependency/ies to use a snapshot version, which usually consists of the version number of the next release (not the current one), followed by -SNAPSHOT. For example, while 1.9.2 is the latest published stable release, snapshots will probably appear under the 1.9.3-SNAPSHOT or maybe 1.10.0-SNAPSHOT version numbers:

<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
Encrypting paswords I am already using X for encrypting passwords. Why would I want to use jasypt instead?

Well, first of all, if you are simply using a Message.digest() or a DigestUtils.md5() call to encrypt your passwords and store them in a database, you should know that your password system is much weaker than you think, and that acquiring access to your application could be easy for any attackers. And it even becomes worse as the number of users in your application increases.

If you want to learn why this happens and how you could try to avoid it, have a look at the article "How to encrypt user passwords".

...and, if you are not using such calls but some other APIs or techniques, maybe you should consider reading it anyway to know if jasypt can help you do things better.

If you are using Spring Security (former Acegi Security) for encrypting passwords in your application, check the corresponding question in this FAQ (below) to see what jasypt can do for you.

I am already using Spring Security / Acegi for encrypting passwords. Why would I want to add jasypt to my security infrastructure?

Before all, understand that jasypt is not a substitute for Spring Security / Acegi, which is a powerful and very complete security framework (and which use the Jasypt author recommends). Jasypt will instead integrate into Spring Security / Acegi and improve its password encoding capabilities.

Some reasons for considering this integration are:

  • First and most important, because the default standard encryptors (PasswordEncoder implementations) shipped with Spring Security (as of 2.0.1) are simple message digesters (one hashing iteration, none or user-property based fixed salt...), and are not as safe as jasypt's password encryptors can be (learn more about random salt and iteration count at the article "How to encrypt user passwords").
  • Second, because they don't provide the same level of configuration capabilities as jasypt's password encryptors: algorithms, parameters resolution...
  • And third, because using jasypt will help you decoupling your user management logic (more bussiness-oriented) from the authentication and authorization component represented by Spring Security (you won't need to add dependencies on Spring Security's PasswordEncoders to your user management logic, and will instead use classes from a more neutral library like jasypt).

For more information on integrating Jasypt into an Spring Security-enabled application, please check the Jasypt + Spring Security guide.

I want to encrypt passwords and I know NOTHING about encryption. What do I have to do?

Simply use org.jasypt.util.password.BasicPasswordEncryptor. There is nothing more you need to know (if you don't want to :-)).

If you want more power (such as deciding which algorithm to use), then you can have a look at org.jasypt.digest.StandardStringDigester.

And if you want to know more, have a look at the article How to encrypt user passwords to learn about how a password should be encrypted.

Can I decrypt an encrypted password?

If you have encrypted it using a message digesting technique, which is precisely what you should have done (by using a PasswordEncryptor implementation, StandardStringDigester or similar...), you cannot.

This is because digests are a one-way technique. Once you have created the digest, there is no way to reconstruct the original message (or password) back. To check if an input password matches a stored digest, the password is digested itself and then both digests are matched.

And why should passwords be encrypted in a way they cannot be decrypted? Because this is safest way to ensure that a password is known only to the user that created it, and that no one, not even system or database administrators, can know it.

Behaviour What does jasypt do to create message/password digests, exactly? They are so different to the ones I create manually with a MessageDigest object...

Jasypt follows the RSA standards for the creation of digests (in fact, keys), specifically the use of both a (preferably random) salt and an iteration count.

The salt is an array of bytes (randomly and securely generated by default) which is added to the message prior to digest. The iteration count specifies how many times the hash function will be applied to the message.

This means that the process of digesting your passwords (or any other messages) with jasypt is not as simple (internally speaking) as just using MessageDigest, and because of this results look quite different.

For learning more about how password/message digesting works in jasypt, see Encrypting Passwords or the javadoc for the StandardStringDigester class.

For more info about the RSA standard, see PKCS #5: Password-Based Cryptography Standard.

If I create two digests of the same message (or I encrypt the same password twice), results differ. Is that normal?

If you are using a random salt generator (which is the default), yes, it is. It is normal and, specially if you are encrypting a password, it is good for you.

Using a random salt offers you several important security advantages as you can read in Encrypting Passwords, but if it is important for you that two digests of the same message be equal, you can set the salt size to 0 bytes or, if you prefer, use a different implementation of SaltGenerator.

A salt is also used for the obtention of keys for password-based encryption and so, when using a random salt generator (default), two password-based encryption results for the same original input will also differ. Nevertheless, this behaviour cannot be avoided in password-based encryption by setting a zero-byte long salt, as a salt is required by the PBE Java API itself. Thus, in this case you will have to use a fixed-salt SaltGenerator.

I see jasypt uses salt and iteration count for creating digests. Does it also use them for generating keys for password-based encryption?

Of course. You see the use of salt and iteration count more thoroughly explained in jasypt documentation when referred to digests, but this is simply because many people wrongly (and dangerously) forget about using them when doing digests of, say, passwords. Thus, it seemed important to remark its use when digesting.

On the contrary, password-based encryption is usually done the right way, partly because the Java API for PBE enforces it to some extent. Anyway, jasypt offers you the advantage of transparently dealing with secure salt generation and checking.

For more info about the way password-based encryption should be done (and is done by jasypt), see see PKCS #5: Password-Based Cryptography Standard.

Why does jasypt number encryption support only apply to BigInteger and BigDecimal?

Because numbers are encrypted using the byte encryption support (encryption algorithms refer to bytes, not numbers), and so the result of encrypting a number will span a higher number of bytes than the original number. This provokes that a 4-byte integer needs no less than 16 bytes when it is in encrypted form.

Because of this, only BigIntegers and BigDecimals are supported in jasypt, as they provide arbitrary precision and so can handle such a big amount of bytes.

Nevertheless, if you are looking for hibernate encryption support for Longs, Doubles, Integers... jasypt provides support for encrypting them stored into SQL VARCHAR fields (instead of NUMERIC ones). Have a look at the Hibernate Integration Guide for further details.

Does jasypt store PBE encryption passwords as Strings in-memory? Isn't that a security issue?

From version 1.8, Jasypt's out-of-the-box encryptor implementations do not store passwords as Strings in memory, but rather as char[] objects that are zeroed as soon as they are used. This improves jasypt's Java Virtual Machine environment safety in extreme security-conscious scenarios.

Besides not storing passwords as Strings (which can pose a risk because of being immutable objects), jasypt does its best for not creating temporary Strings storing the password at all during its operation --thus not having to rely on garbage collection for removing these from memory--, but because of the String-based java.text.Normalizer API for normalizing unicode, this can only be accomplished completely by adding icu4j at the classpath so that jasypt can use this library for normalization instead of java.text.Normalizer (icu4j provides a char[]-based API).

Problems I receive a ClassNotFoundException when I try to encrypt or digest data.

You probably haven't added all the required dependencies to your classpath. Please check the Dependencies Page.

I receive a ClassNotFoundException for class com/ibm/icu/text/Normalizer when I try to encrypt or digest data.

Since version 1.5, jasypt does not include ICU4j's jar files in its standard distribution, as this dependency is not required unless java 1.5 or older versions are being used and the ICU4j library is a very large jar file.

You can manually download icu4j from the ICU4j website or from your maven repository. Please check the Dependencies and Jasypt + Maven pages for further information.

If you are receiving this error when using the CLI tools, check the CLI page about adding ICU4j to your classpath when executing the tools.

I do not get correct results when querying a Hibernate-mapped entity with encrypted fields when I set conditions on some of those fields.

This is normal behaviour if you are using a random salt generator for your encryptor (which is the default). In this case, two different encryption operations on the same data should not return the same value (due to the use of a random salt). Because of this, none of the fields that are set to be encrypted when persisted can be a part of a WHERE clause in your search queries for the entity they belong to.

If you need to query encrypted fields, you should set a fixed salt generator to your encryptor, so that the same text encrypted twice will produce the same results. Although, be warned that this will only allow you to use that field in EQUALITY comparisons inside a WHERE clause, and that you will be reducing your level of security for that field.

I receive an InvalidKeyException when trying to use the StrongTextEncryptor or the TripleDES or other strong algorithms, although some algorithms work alright.

This probably happens because you need download and install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files in order to be able to use strong-encryption algorithms like TripleDES.

I keep on receiving EncryptionOperationNotPossibleException exceptions when trying to decrypt my data.

EncryptionOperationNotPossibleException is a very general exception which jasypt raises whenever there is a problem with encryption or decryption operations. It does not provide any further information to prevent the encryption infrastructure from showing too much information about what is going on (we wouldn't want an attacker to get any algorithm-specific errors...)

When you get that error while decrypting, most of the times it will simply mean that the encrypted string you input was not adequate for the algorithm/password/keyObtentionIterations configuration you provided. Check that your encryptor is configured in exactly the same way as the one with which you originally encrypted the data.

Also, if you are storing your encrypted data into a database, check that the table columns that you use to store it are big enough to host the encrypted data (which is always bigger than the original data). If you are transmitting your encrypted data via HTTP, check that you are not having problems with the transmission of BASE64-encoded data as URL parameters (BASE64 uses characters which are forbidden in URL parameters, like "="). For these uses, try using hexadecimal output.

I receive a null output when trying to encrypt/decrypt my data using AES-based encryption.

Since Jasypt v1.9.3 PBEWithDigestAndAES algorithms (from the JCE Provider of JAVA 8) are supported. They require an initialization vector (IV) parameter. By default Jasypt PBExxEncryptors use a NoIvGenerator for maintaining backwards compatibility and decrypt values encrypted with previous Jasypt versions. Establishing a IvGenerator (setIvGenerator method) will solve the issue. The IV should be random and only used one time, so org.jasypt.RandomIvGenerator is the recommended one.

jasypt-jasypt-1.9.3/jasypt-dist/src/site/other/000077500000000000000000000000001360667575700215235ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/other/Password Encryption.svg000066400000000000000000000665401360667575700261740ustar00rootroot00000000000000 image/svg+xml SALT HASH RESULT HASH FUNCTION n Iteration count SALT PASSWORD jasypt-jasypt-1.9.3/jasypt-dist/src/site/other/google-analytics.txt000066400000000000000000000002601360667575700255230ustar00rootroot00000000000000 jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/000077500000000000000000000000001360667575700224145ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/css/000077500000000000000000000000001360667575700232045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/css/site.css000066400000000000000000000000011360667575700246510ustar00rootroot00000000000000 jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/images/000077500000000000000000000000001360667575700236615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/images/jasypt-small.png000066400000000000000000000203121360667575700270050ustar00rootroot00000000000000PNG  IHDRRdԁsBIT|d pHYsV0ptEXtSoftwarewww.inkscape.org< IDATxwEoB!4S) ( xU.I‚ri . R"EI?|3{ |Orfgg}w"<:C=x Ri/H=M x<6x Ri/H=M x<6x Ri/H=M0Zx8M=J_5 v?=gBF/-;OVKxj_&x<-4!ԛF{?#i~--8y/'x0z׬ׁ~F/HK2 B5ڿ7[۪Jh!ti>-M⿷0ZkA-  =>kb4뮎 UQ+soJ^`a0pKcPTp4lǤI&~ZewTH&mw,@m;MƸسR%sZ?WsI{g+0c895Ϧ>v#i&7Ik.ݰТvkA94'6Qa2X6?< -=JOVgAd^- G}'\Ntum+HR>цuJ/2ynŀS]3D/ɰdí$XӇ+uHSyai?ۣM{5ߤ0h8܎ Fۚ 4ⷨ ҉:I< 8A% !4/y~#^F]\ RO)U?kk')ŵAc;\S$~u)b= -}o˥I|[Sh6Ϙߣq}IgEo4{AZ>j]j}_oeR5h{Ǡ"> QV!hsAm `AX.]cv2iQ›vH= V򩕧7QbTSYߤ:==7;-~Ee~\IA:UA:4iFSyA-f>N tMZ&pwcpe]5_NwIAZ;_F?ݡUg`hMi7J(Q ÀkMzt4:4 6<{ Dp}S^ R׏u6a|1+Aͣe@S^ ҢHRԺ8^'4{CRpbGV]T:u€.B(o0t)m[qzO%z%H!]F; apj<=H3lY{kt?dp} M.ktI2.װd6eXkJSNOlݛ"g̣q~A}>jkW+]!M;tkHPK4/1px"=z*ϥ}hQzу0ڟ*y>ܽq;L{*z 蓸\&qٴ~P,HaBFQ/y~jUipBF9Kc}3//TmKWcFI$.J*&PbFMq;[t}Z-amHg Z EKE![ 蛨3OAZ(W\Ax;Ep'.feϲY3>atXFfڭϵ(Rb8lѰ~6iu4UH|a%KF碕X4+sgޥ\K*idͧT 0Z- Zҭ.sn` iʂ>|t 62G4qH-U퓭⊴zwڽF;}U'dэ<8ȦJ&h2E0MWEA-&v$ hfcx]zdy]lBqAX(4hU4ME1 NBmd6տ;6.iǨQTkBvq [$v%7iDG6 v`C$n5bѪA l.{ew*s]"yKi[P>/M0-'{AQBualS//Ie`8x4uKd˝>T'iEX}U2~} 5Ժ~&}-+قa/0 ~ ThGyD`&}P -*[5 !AMBmOˠ;KL0 t+>y;4| Iؕm k 13,Mļ:BįagrQ$HFNACi~`vZ)|ׁ$MUr>+7 }eS+R=uQ{S(I L9f{Ihg0~ѿ$i,m\Tst74 E"A:xB< ЇВ2w0/y m$|]75nyCz!H]v(i [)5.4EC]@ f7i2p+DZ Am QSNd& ĚnB#2嗱Y@%$6AOy 4X*iѾhĕ{عOK#44/ h%,Q6~N$ۨq,js1Am.y>e\<Q96 ҷm4 i-^ ?EM1i4[&OmڬTO[:g@)#[Zhwe:=MwStO4\ zE -v!_@x] ~a4MOAo7;})f}?.kTXYfk4wY ލjͰ-T~ιQ*׺׾|&Mstn MK*LWDwVqOs/(uf څȨ ,u'IG|;7$n./`_]wc_A}^UIOnX:B3J \-d i ט \kxzO\ZzA &Mbj,EQgۂԥCg{:fQq;nz<%H'gto'[ }fx>TtM0GT5a1" n/gofDOxlrKsMGIr[2fQ<|(殽>z/sllhi7,%o5 ż9M[:0y F*"bo..^ofz㳐ZWDWFBzMGvhJТ ǷcNϵlI1f3MD SWIDAgYþgahDѕ=hruCDFJc̉sWDÊ ЀE&o9N@#ЮmtA=y@i`Omh=O>ba 73Ѷ} M3?$Ff 0Ɯa8 U.'6P*4z hiƘDd) h0 hm1GةƘyESw1JqGEAjS}]XPZyF}ג FgBoO? |IRS?ܒ 5/"DQcE1γ0pK70skƘEd p1%9ל{80+"O"{cmBD&w130`[c̅v? cfbYo=cE=xc̿l"1u?_c.q? ߈-Ƙrd9LDR9c"rp1fu9kC!hC1)cu"Z `#c,9c9EDB lm?Q(2Ƽd1aFD1Ƽf#"re+BZ &T[s&)rd=gƐߌ&S~u8_Mg͂4Y0EjiZWYXsGp]1Ӏmxfˊ epyp@ݱeq@>ܱ ~>c}Dd1&+l&DADhmCv]3]"WM1cn/'8(A;0zv>6g"ơJƘƘϩ0AMNMCPE#{Cn-Ѫ ͻ/mQ>|/-2W1iQ`2 1Ƙ7?eh8Eda"*0OZ&c7ܯDdcL;_ rS87P;.?(g o,,"'9cfcre {2_~sl!"-"?BMi)O,}+vBsCahpV"r,j&bgC1<c);݆$/㱂-SD -MVAi y&qj -܎;AH#vMNMV!5¨vI\ !"Am`{cfed>#"ˢZcsֲ,c粁jt)e4  ` Ԥ0ێZgIƘ[fq:fBb Z8T`\.m3-H ey8~c Ƙ7Qq֚Ɍ4j'-fˀݨ/;rԗj㙦ю2%-"KV"Y[1viO8:(lhޟlVJdDdidvVnUCf.1ODwGc˛c~ |)u<)6Xc<#,s#zq~'*̎Ƙ'{9-MKia^½&c.b3EC3@{byeYH0w+`>ޔgEEdqoGAƘ'Dd20BDFcsF_GD Ed4eVQoCOcEd,wv` a`| VE]v81Xsx 1RT ?O&* Z`H6E wn[8󶈄"2~VsYOQ[ƘPA| H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_F IDATxS 0=g[6#=`1#JҤ}),!"Dyu +`Ik:Ҷ-28d: "KKKʩ])3g T5yYAU}Lq"{?ڽaHu1eWU]וU}3[Ӭf?^m1  %Hzz:Ȉhc``!h4###<޽-vx1a={Fs#{R SZAOgJo۶Z 9sfnhh(ٽ{ h^ 0 *̒3#B.zzxSdR)Rs &A_6}Z/k-qU5a=BPe!iAa~ #so7M41ϿK˭̠V3Y(Iɨܶo,Deoָ/kGs]N MEz(ދ9#A/OSp0 8#m(s4 =w4i!DQG}> ~Z{"( O#{1q~%IT&@ Dk37kq4hqNӔW!:?φNn%Ba'Ǹߠ4sПMJ٨Ӣ2T^ǣ! CjxZ,.,[VyV)uVy1ƔefQJaX Q WB|Xnv fu'Aӆ*tRR"z!O0)%Y-';Oau>-a&_2.޾[N0E>' OԝNaƈwsvX*uc@ao@Ñ̕'BSgKj9α{s}.ɒ»@xxߨBt:Qq~;<|RʷD"VEA(WZq"@s ;]*\Bmpb3N;ׂC.n)y^Ied^"⅃FW{$ oeYe3QJ4URtxl}X5%9kl`ڈ;׿;ݾʃjd?~zZ(?2c"*1@Ȇ)QY&KrRˁI4KhƞCOG ב9I8d(E&Kr5sU,1~a8\Ϡ1}qK$Iwy>>^о]]dz~nALs,9wٌRVJ .EQ̲c ިs`ںݍ\);T ~yMa]@Dm}q09=-y䄈rXS/[Շ[L7߷Ho D».p]1O@KK;C摉)aɊL FtxSb u^t<;n sO8ÎF~T'4ptyqW .EՌ> ce4΢sqϻ{a[Fyy /' "9D.s!ml7|.PaʟbY^^V{>Fn+I2 J{SEw F'R(3q_[[ӭ"3dUN2}Oki^)_BӑҮ`-,S[2=;FaQΚa{53R]V4M|:R>UNNN4}_Avvloo[,hivuu|Ӽ`SJ{ Tu2tOjwtYuYww aM>uӺ0@C!y0gFӁ2\dnLNn=#]^5AplG_VW`pY:"M9btÿhFQ 0'%)33LW]\B_sƝqgawƝqgYY?]nHiRiH=)\d4V#9(8A~*~H/`u*RJI?w _1GKR|H!+pq8; v3 ӝ`3Lw`0 ;tg0 ӝ`3q+%u{^\f"6cӰ$ uطිJ2])n1A8C?XQ* q $i.I'ǥDE:osP3HUyz7xĔKnsLMOJj6a=MbS]%L {G!D_ON>?$^-da:ECsxx{||i/:_'g/_4 pyݿZ-|7]j_u}jKZm Cm  ۭiZWUUӴZݯj''e&۶ie%n0XpQM+P "1q4) SU |nNv=Lœ+.^S|> F#Yu~~D"@ d_tSo|Rz4ỷGCoBV??O#?&=UUc``ӝ`3Lw`0 ;tg0 F;%k&HIENDB`jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/images/passwordEncryption.png000066400000000000000000000655571360667575700303260ustar00rootroot00000000000000PNG  IHDRHV sBIT|d pHYs``MtEXtSoftwarewww.inkscape.org< IDATxw$Eoxve@wAKKRU@DP?r 5ދ S̢ IrXHX.l>gSSSf̙sv<9S]U[]ZT^!"o6^n~{b`$UsJ{^(EDJ730u;']CWg3À0u-ZK=D.89 >_* ,Rէ8&uU}؊3 6^n?>1r쪪J^(BU{ b*oaF'X|:rwUYֻ{m;yWN83#ydMd[>%7Z׿XQp}%ֱ <.oe:ml9::D bQ# x1ԫH9FDNSՕm pހcֹH?0iα"T1"`{L=^'#v09>/"V՛=q^\^7R~ ܗ=[GJPpB~ƶTO'8}~>)"{xh~ Nt/\Kfi3IJU=4>CvwZzunGR:XOXd p&5LZu S|'w%U}x[,9hPd;̳:9U UȧWdnySa_DDZO.I'҆ -LȺXDOO_IAہ Z_0s3żاlsmiTu,dȁzFE"Bz@Tul6C+UR_P=:9WL׷Zq;(?uC-",x57X7AUSOL/q3q#שe*ɇU9Is٤wjMU?鱝Km&jHOHT>U}nC~2[0wwӥ_+EdnXxYUhlQ-Z حDd:=jUUb| h92C\\E=+07c_Jb[6.3~HUvrT,nu֡WZ-Cz5uLK+i\蔷&BJ/S&0BD<w̒ה,Dd@UL.rFDn=rU3wuloY +^U˂IVaM>&"w`VԀ}16urlf@w&oZ| y{ewU}y*EXDdwV-=D[bb4v G0uaj$^MwJDż2zY9d8̋;1-M}6}=潪`恞aJ{9*\%"[w9q]W%ʍ~̊=7oQ՚;f 2-#D̋RaZ`f+"#:5?tȏ 0=Ed(`Vs^yʂ[=>("ü pܤ?p.]act`n3$wi҈D'Ҹෘez`ST1UzznB"rfP~r"eN:+ۊA=sۘ@}7*"`1kIz#et Ö /d)gqu=|^"" 9'Y|'ǒ41{|ma%=UID6'm,T~<)a-'=Yw?@uz51Np @ h@@ 'e̱uωMS" "GK|J䵐DEӽ'@9ǍwEJ(4p(ʾks99Q}XDjSTyUTv>묳turЩI>zgDRxN%™j==ܻ;CDޚƵu::wYgL+Q)*SW>Ͽ(SJu9>VTUV/yzU*gu?N8uK:묥{U}}}PN_aEك:׋}18uX${)l 8eOg!fk/9mt~>$ѩ6N 4jU(|PUqpr>iU$*T*j{N!/WNi9:5SU*bw1@NY:ӜJ%ihEX7mr 8ƺ! "h#o%N]TZfU*y6{UtVXQ*Zëj>vDݨS66,ҬpgV}W1-+ʫNu4|ƨ'C!wM!N-*}}}ji08<:6p2:%iddݮNiZ榓Q8sL0Nyue5^nEĠg/[:b~unӘeWҚQ3vGުNyGNJ>IͭYqtK[ۙYN*c(Z)nv9:Vv+y눭gkDFFc"XαXơd*=\C[)X`N CǦNRܖ}r.2iϪpYVNi锆ZKI7^NJE%nt+7-DZ|q[yԫ=o׍ҟ:z]eʔLE=TK(S+I%`¡a,ʦC-SW)Y|\|2ePWz]tulf dܫc:c_-8 +;TvzIm(n9b{1myWrc_'k<]鍸SgoU4zU-HJVH;}r`"hЪN>da|tJ=dK6e 3$R9{ J+jl+MHTe{^ܾpeinXΊh8IJbz 3hgkWvUɅc>'e,zV}tT=d`i8C v٥:H'ONΊK'ͻqD:mhE.'_:HS vndrXǖ{{ 0|+4NYcYΪ1J}C} naPbcQۓj|sdk:MH"$Vx,\C߽r_K1ː{M^]qjU2u虩OO C[X>XrtncY=~)7\9.\;3dl[Do'1t]/aT$MƼ`Ұpb@1|;-CHJur\tx ur¹:q\%:i}!:GGr3pX:ƃj{^%~eɧ#?n7w=:P 3d/AaYȧ W'J 2B:1PZkI4} L+`;quj@'ۉdkG'Q/GccfW%Gڸhíֵ-OzȢwtp4,l<8+k4=f CkZ'MQ֖":t3PVnN%t˓=NTY}vpˬ(3 i~.y-0v^ -9(GEvg48\=d,R9Kr_ݰ{G ),jP6(C91tN.r\Zk  wS/N]35>b:e j3W2ˠSIs_eƷíϮi =C^+'jepaҫh;N G,sMזkPCif+bV tŠ㫀Y2 -vsO(Z>TJgX 76HNnG;/+%v픩USmc C^ JǣO2,.Y7HUqsL fİM7WN9@>:֌' SV#C.Vu[`xvTW0 m@K=eW~[αIJݰ-7V9q8eyuŗWVt<:x!iוy:sٵa hz[>GHZyC eA{թA{b`9KjKej rSv۱zzػA2zԳNM۹-ӎOV&٥7\(qn<\`h<7NpW]+`CUĕ9LCWթ۹eѣey o^E2|? e}u:Y2ʪ>ǛѢsĦv-yJ~P*n32ن֩fevv>{ xdgILٲtm瞥W;'N:gYh_܋ wVfOV k 䳇nA(boڧN::%u/ ۲j2^'ftjxͫQh,?(r_K 3&Ӵ˼i\V:NV1爿 e}zeJ&w+K/#v ׹yݺRM|P*vCH?(_;)ZkDKyiÙlDNpWpV2eLlSYp<9w+3eNϻ`z<~y7c588;oǝcJA[2,^je/<;4\-?Z%8[!`1:Se%Bp.^ƛ3$R -[ޞwαYufy+a&7^n{Uu 7CN=^38,瘿VpoJ:@Vk6Õ5ChvV֒RU2"7T~#Cɷ=@qXnNi:-ꘫS3i)ko^m@w^.C:_v^8~2}R aYgbd2w߭<,ya7: gR?.^7nbv0n8V04gY -hݑLscKjEҍN.N%ԎeK%q,$a<)I %k)7PNy:-+k}6]Qh[1Ye:熝!Gږ]TͶ)9wbXNu%xˢO_;PpV:6qujW)O6R۲H nFLE/z`@awReq,Չ懬Ai^0ǐ2sIm-YqmE/~ϪE8a^pQ^Q7\~cistSUOqZk3Ͳn;D[2NUꆆlKh8!+[!z$}]NM:y V['C&ΊzW"ÕW7aKW]`++O/ :-EyvN7.8Gh1T"ඒf eiX`ӡVZeYy5 C=NY/K IDATORӉagXN̻WY+2ʰ0K<܄ݴRzYe_yz+.8̼u L`tʠ uʓ:JVBxk|:f\6 :,/nwQv ׍<g ѫUjp<_DrM_NeoQyu7R=>T\:5yQIN %0J^tW4ʖg^AH@^%ꜷ,&G=b(i.S9^B nuӯ]ө|:z~M4?TIHC^!)m,uSVY:ACG `ɼ:5lX6N۽_eq 'ͫMX6/s,\>amPB mNejljG瀫2S%5}N9ɹǭ++P[퇌ZT*T*etjç%&˃ZЎN͗ujX= ܕgJ"A6\;h%w+01O/96SUeŊv^e{#"MVߊks'%{^8k``^x^x;A &d7guUD)S7<)J&&JK׫^p [O;~ܵ9ڹ$7/_>vNT`d啥pq .@ P'8@ Ep @ h=GD> r@/X`}r䱰 +:Dd?\Uݵײ s @`4Y` C  Yx3ucH mh2z =@ 0jC/dtz @`4q0 G^A='Cp @`4qFz K@@D6.ED*Gp @`^`0\ uI@ sDq9UU7##U CTϏ,FxsWCF@@ V )"22(pnE% ^#GD6⹾*"#!\  9OUݲײ s @ h@@ @- @[$mH "8@ Ep @ h@@ @- @[$mH "8@ Ep @ h@@ @- @[Z@EDӀ){2b a)"-M-%0K% `&N|lMD^nOTё*X3$04`p`x'ZU]bSr&1i'`,`ȩܦv@@`$8@0NcIJxnU}$g xr7 Ӂy6GW7@<T0-i_ |XUiyTu1pm8HN^+1:UX"8@G~]!S=̃>\\ q&?"KL䷪:;IIp ?8XUWT$_x`_3 oRz(f 0G0}lᢪ;U= p|WD 8@ۈnTuwUruNE#ftvFD鱈@$2"2MD \x ژGUo6,*"Sz+] 0h 9xYU?{,ֈE3EdBo F@bV(}CUH=EU1oΟX "V@`d$PLgxF>PiH5Ր9ݴt>+x<"n!WUVk./,)#\U(r?-8_oL%2y"Wio=XDV*z k"ݸq[DU T8TV_9>9:8U~mu N[!'W^UQ{jlYfm5{7Ne``o`` ZtiuҥhѢV\ykZ}k4Ddz%7.;a5 0ce3kO>mjm.Ҕ>0fq9s 6 yBh2wJCw? x{qߗbY>{h;*s S'gfbU/^v7s'/$x-Z88Vg_>z6 V|?+l17%|q;uOG#݉˿zZ _3._|mQ{?a8gkn=8T.+`ޢ8 ZD{SHW" l,PUM&pg,U]1'"O1d%v=7RǬ0--Uor%Ԯa^u a}0#vG_ g%3WF+f_6:u  n #==g:r.?Brеڙ|mSƳ$rPwɲ|?sr.ׯ3y[|b#g>~RfMV'Ȕ#5~e_vN1{0}X ^oX 0`s̰cz.~[q|(ɣaGDN~ |U:^tN"w3>9> o泰gȁSx'%:w#7Mlӳ}}}̛7/ ;{{,D~dݙӟ$>." "HN8ђ0kT4H{bI5Y2ٳQT0EPW"җ iU%H.,=ӂO-FDHLUeTuGupp)sFǏ;N:~xܪv2ڧ`oUş~tL8t+_)?W9qGslf?\fQ2yp<#ZirM!,Kn]%.9x~?! ix,=N-?37sӃ3 ˉUh~$KN7A䑧Nɺk|Ͼ Z;I'|k?cWn(sџw]UXv,O_Ftꪗz# bnFD^6iM:mW3_;UYqk̯$i}'`;4~4پs[nepB]hH 6Dqs=Yi&B t+]x̓\T8n[s'#.cȁ5_8jpSp#n3=)b;CV:O?\y c~=tzq}y΄w;#vç.nCU<ޔ͊^N^Ie1M|@9Xew'sz8c\v-l5oÆtn~rU}޲::%"k0g[7pY|3tk0xs)" q]dB#ZDJ=|"t 25<lHIy+>݀{Wlт bV0+~N-(ϳ &66a-w# y!|to#M4&(&(_6I6)bp¬8:lyE\}5e'2i|y)lGefnك癵9Ksx}/Z9gˍe=uDH3f'!j`/uV%HNV wa&Ld C1-5<|,MIdm>|ށq&w1くbzK[+NlYXppWr$lFk1a<ʯ|U>a_F<@ZS`r]wqfb?x&C}݇r+ϿLEҕCX}29vTFrME Zc ͉N?`&}v _Lsb/ޯ0+Rm3~3_zeotlM:UxT*l_2!@gO?^P#=C["}i;O+\vKp6Ru\,/'a:ݴ~ {&OOo{N';O9g@𺍦֏[cڑdeʍ ^>/7e#zt% ?܏ fMG_ wiȱ8fM‡v Ö*1Dl;j&8u,XsO?{+w=jܚ:00TD~q8WmTq ;AmPٲykQL nT>q8ؼqQ VHZ t` &wnȇ~,*8^Om<ጉ\LJ ̜:ۏ~.?3PUYgwVlN_~{;n_''}=<*En/.O(d=v 鵼h'2b`̋FjZ~[L4IAdժUkj5Αlnfʕ,Yo }_xQbX:`c&w@rwx,יPo[O1gmof٪AM_n~ݭƷ]fZ}WoBZ8:I,]IU=<8Z:dk'Ӌ&kUxqT"rE̞̜ubl:UZv{-|ǿӾJRu@V3TKxe-|Ir/_|ŋr޵Πןʘݱq/drFi鄊-ak CDb"Y!oQbf+H8u}; Dy2%|{?CZ|69G{-Dq9lf\g`E ̞iݠO"\䰭-;f}|0“QzAp2}ܢ,|Unq.m|"ȪZ 8OUS d DDUeE1K*l iqOD-&Y|;f$O>/-՘0/*9>j X2azj&XD"9E|6zU=eDd0-ly?To$z_V/&0Y3##85ez]ˈ'1gvA 0ߙ99l+#" CY#"Ӂe,T@iu|6zq6f˽d,|ry"$zp|q@ٷÆXy4"2]D>6%|r?="r^kHY[KUTz-H @mZюL#EG1P.zc ,,ǀF9gbޣ9@:"G:U}"cy2_o3_=P,SU$"O?1+z+UG]n6z,RO9"Vx̶  u·},uY< G!~z8 =@ɞMާV'pp -p5pdAQ: 0[ļsrN$/I>y?%BF)hB p#"X#"["ex=`kUXU߭,<LQlz! ,< x=p%ߪz}ojZbzw`zW7(`^,\./&>xI52$PdT1~;c4 [c8?vc:0SUtګ+"rkRVbE#+U @-#"3waŒQzϪYQLo$V^Gkȯ7Y~^(#8u}[a&o 8?#L̶0z @`!"|q^&$mH "8@ Ep @ h@@ @- @[$mH "8@ Ep @ h@@ @- @[$mH "8@ Ep @ h@@ @- @[$mH "8@ Ep @ h@@ @- @[$mH "8@ Ep @`4po#kJ#"SJdZć lk9@`9RU>ƚk9@`yLU_>Ɣ !L@- @[pɎ۴s+" :WdY|zT"Ncfޔ#;IE"sO(""[?Dw('H-W;OxWWjK*q';^3t?`zEQKINN 7N9nƓ~=/}i"}oss@=`L9p} %cq,9uI8#ͬ"jZV;鱼::SQ>et+{9$LG8F zрg= 'jE,SɱZ ȳN`92k i.Wit9j@i4ۨ1@Z5yF1iFVGq藍-:,ⴷ\/oA^#梴c?`*ǀyZua"QY'ip8u"٪jq $j1a$c3hU]g깶XGc΁@kΣ(11E=vt*U;S=?f E5bzIӂӂLI勁Pqn(zJCYFK"X6\@vpÀ]tqfQ9ܚsl(Is݉)p#A! WeujEVz=iӲN AhjҪʵF V4i4sweH\'R3A֍`N6 չ0cDU;asls ٖi44^oU4CƜ(260Bpt*JTgz1rk"3C]8fhN6^p~krVq>ξu `^$)SFpHG|{٭Y:N2XP^ QAa:G{#q{So FL坷L9 dIXv!vBVZ@D܊k$ Dm~؇|XPs :U*8QJ'c(LN5$1|hU"_y0TcW>S1*2,Y>y:ѸGcʁ]gs6b/yuCVdsam CϲY%P_GZAJ82ߠd[Y+ @%V"[f)VduWG=;NJq Nq>qc9 Rq#Ƥp/n)XU't*:Bqs;Izv'f1}`VVV%N-<2ʐSuV@{^q稠WF(\96Lʰ4e˻hd9waYd||l|Fd@)ʽD(VF=ۃ,cт"m-=F<ߒ<# BüB[1Ķ4 aMFYm;*UہĨ:W2lhuS$5E5mYF6e`xm4:n]!f/f__>`kfe@Ndd<ֻ֩-S qk@= M3p*HpsZFLT" s*oȨ8QF c΁@{LIu!vC.!,(m i|mP J/Y=CoR0ZGa/GfU^b3d҆Exz α)ۦhڬ1HCN:JVL^Po܃w:y{E  cƐ9ixlVi*MJ6jPVx E cef(>Yk/s~?ߙ9n~~yֳڌR+Uz]豭mu:dj+'|Ik1dIާ1b"J)&6f; (=}C\XS&y4Jy4SV\#2x9uUEuTmL[@q QWw\йoK۶xJe[*DV G-'f]4HO+K\嗿i1WH lN;9rZfԥe569}/9Li>_QYe}`Kc)S4\Xq0-3\ -F=LL-0yd?v*a 1 dor0rVUA?-K3`6foIU$U:-uO#fhR2AmH:zRDeuLjWpiTb@)\aaK "{M6$d#1 \ KH\s>ϑXw?99rlk;|[@rJ},Eoz,Y >2QOp ̷@*"($zfcOG@Jw 7~;sa9'%9Ev*6*WKIqݏ+ti,Շ3ezÍ-E (>yƴpkCe۴L?ն Õy$h#f>)MY2#aX_0GL(HE3La?+c!,:rT.0;EaG+,[b=0߶%*uU*2-CTL}22U P U7A|1ka07]X00Ej^FCF+4ы }`0v`rLT$3jh'lS{E`nƜ0Pi11F Pl= 7Tigk1˹,N"ĭ_v[o՛4Ӏ˹TV9QHY:G2(ʭʭJ*b*J]y%`? 'e|=g[@(uY!,ubLV|3nyd*#*+:օ5E1PJᄫsn)elf鉄9sm LR&}|^3 0 kcۊjh}QXu}cY\%I)u^7Vǘ=fk{s(>J}- D8$`j?F5DPI[ Jjm+jXg=إ-lը qa|rjm쟡mg(csAm\X^*! P92'7ˊJHF TȼrABX+cӶR7(r#gPOwϰ)Lah~@VQX+-DB Jna'@VJM)ZKw>Y;mϑc:3d-ܲVЌiC1vkc>RS>Ex-aP7Βeiԅ)Byc*R0^xq|p{rSsUJ0n_;/eS|/rre+hʹ=x|'r=1?VQ+kE(1TqVFCT{)|FR>M40QR\[vKF9QƐ0_SY~ S,`[B!WH67L[Ap@2Ϋ0i}uXŘ_$pR25])?ULZxJe;ei{;{mgfj-rL\X,T]19Z_Lqr,%c+Fǹ6T6@ +ŮzUq[ cdJo#pbA˒% hڂ2UvH_VG[9L5|ˮ*OTh_o 9KP2QXIr|bf9% !Jb@W!%2[2'HriuUwsˠ˟WR C=ɶ&'o)ª3$DW PYYk'~Klkf:qHɵ$L)SyrH[]cbWe,B)H#dR%[E;O}U[ZTW'kuQHO"aˬQ`%Y/rLb ntXmVP+恬xHr/*Ӑȴ*y''.mSɦ!Oq-W&Ӵ)=-TҰ0ϥq#QH XxXt#YݝylyZs1K}^L>LCIxYr t  IDAT]ZHږA_vBk |>CU+8,iCvu@Eϱ1ȱUz:;ϧA¿v}Ե27Lc#ʆֻҽ!m*&5dYz#'  v SPD~gMX<;S?{>#oW{|8w8P M=ǚx,npDIq+% x>wv;͵ÁEt6RO<F&τ5a"n<g| x}'! "G.BFk̽ˣ{Z qSί7ן*"w>zZw<&CS9p>NUS{ާ,(8\UƹN{g=.0ǖ@N{cϨʶ{Iz> 8G Z/'O}T`m俓UeG<$o0H7~_ ~_U?iRyvzo꭪Q\fn_oi䣞>Q["<4J=_pM]ICM{LjHQ깸wSek]A@vcK ^jTM;/ùRiP7^9su.TR 8w0&$"rvTrU^#~Fyz+܃ w$<[EX_S[0JUn mDby]iբu ƇMYwĵ"r&".F[np((َq5K Gckyg%"LPvt^.|\>&@!-"-?B_Sw? {ǕJMê=snUq p]qt؊.ɫDz5u3R""/pG؍e #KWĕĤ-"_oD.1˦0:&逺̇Iڬ~pC8xdOؚ8_Nz B pR KU߅sչ R4\p,۳ȍ8q!q>!9֛Iu4d?t-פ{lh1Hꍪ2)A2I|9Lqxio* gqS/^i< {y |SH -U=w.&ӣW˺~7&LťvMxT6ܠ#hº@j\o#ڳA]xLT愽@: " z1'q=+_BO^j0}¦UHUݭUտ`%o<]1) 9QD{C5~xET"" o-U=7'%H_Gzyߏ?&WX tܿXhkU`햅<ms}MLnUDށ)] ܀ߤ*DzZUE4r,e@k4a?)I;VX8+@E"AWqY6ɻ-XDW?I /Q.~!v!^+"UFOp{\3qg'n~q:+ C=""Y[G,.ى<օ}=qќA{spJBq>QY_^Y:9g#]wM;{p,-=ҿ.Q1Qox`y뀧FyL {4 |c_#wƛpA<*顸N=PLs4ZHݚDM>rexu@dzgRO6=WXړq.pNWޮ6żF}"npc>Ɉ9 ^~BD~ ^;p-K7hsP?/D V{Py|4Ίv-B{ {jQV uIENDB`jasypt-jasypt-1.9.3/jasypt-dist/src/site/resources/images/webConfig.png000066400000000000000000000430251360667575700262760ustar00rootroot00000000000000PNG  IHDRPߚ8 IDATxM$G&f_(bu \VH tDZ0oTBXYP F芞F i6=EyzLJy/nᙴ7ã """"""N=DɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@d.PUUz@@@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TC7:zκj˞HeXpss܆,/"\]]>\]]r|.mZfUZB!l6헗aٜxf{p TC !d*yenY뺾ofs"mhZ=T_^^>Ͼm6pwwœzo7Ƽ\.Vs(Ps[VO~x'Ǡ@0“IQZ,YVa\_cu5'{]%wקo[&{nPOxɚ>`{p TSOs'd{ UZܱ^I㬻RGrx6)P sss۞U TBHk S萱7ϿO}RSUUާumXpel6޳3@PcP  T괼IvMN*s{Js(PSw6&SO+1wE*U V Qssr<VDOu*^QqRrvLRJ @0h;jtssjbnN[Ѥjwy蔶jڝZX,r応It=PmWʝ=P:vEƩoZi2ܴqn,*YۖӶmsƑ}>%..WyyZۮ9֝r_`1'Yx:'!<~OU<^І\mX,&M|r&rkַ}WIp}W}ɣfmǐbӵަf)Ds9zP q;^]]^vdhYQWRN>9_w.& d&l&7IKw ZXug*gs;Ur_ԩm߸?:eYʔs橪b*5!'M婿GK|d}OrsTprxLXG۲ۧOiZVRUPvM;u}-m_`J: \R,n['mԤ+9s@.Mc'S]cW}c}ѱ~6W̽>gi TU 1BtvNJ9j$ru>jȇXUcVWڤx(qv}=)t)q{x{2UuA̽@}O_sd:r5c&>syT}LS:&U.#wMr _{R1_.? zncziz[ھ3g9!C,Jm/;2u4y. ?`y߫빍WRy'!2:r[Vl,QԤ~f,v,O _zޭc섾yJZU !>,8uc3~9l6uvZe}:kֶT o啴0O T8ۉN)EQ]ky1JI0j[nj|q󺸸f www~bKutGQQ澖!n}^Rix}mcR%~V%+̗U Υ@ :-wg>,Q-p}}6ͣ)'R777?mʾWWWWyYn* vՓb]1w^e-p}}:yr_!syyYз#Q"\]]ɾJ(_\\1tWRN>s)P~umm˔SO~ TP2=p TP6m[pU ( %^fWR  =TU//Q #PKGzw1n @0 h^M|yN.[U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`1UUUgE 弝>Ev`^sY.aلPUU=]~Ḁ@jJNiX&&v}}}!<6SSѶnpww{bHoz~%]9/mJ U TN6I+tͦ5ScѾn(jJ A*`T/A_k<}tc^:zK䰼@U ε@&kJ;oZ##Sqqm ">߾4o縏סkl9hĿ 笻m4D<ݯB2W߆zWǾv[6G}lGsߵo]w[z]ԗU٪Q_9v夾-ESǜwng$,J: \'Nݿ׼iIXD Y˨>q;y;~0dlCѶm6G UU)|KQ/}ڶa}\S/}<&wY]%}u~ץMc^ħncmC9x!bjOJR^w]VGּo}ٜ$]es9u31v2`ئ<>S)O!}mw߹}NBzS)T}cj~U=er:eC{2!wlS[?%od)}]nsc1m6UR?χ[%cc.m<}oC,пcN;YUuA*^z^?G<j̤b&?c ]ƾ'Zc'mczK-5Oަ&ym.~QO[1.ui=v?SmpzU@|zjOOˈ%L]ݪ~!o3tS'&ި51q>_c =P)YU.UqrUx]];YbЩHmWN]|̐}XKsMmPŘm;>SmNbNyRC vUd1j:Obulps2dm1\UU=J71qÔ}lSߺrr|cyLʄc>o(~bRG+t. a>uiSL@6m>SέgUU 1Ess{{Rۧ?Xjn6ݧ}R|,m[l?b\6)q}rz73nڏC\\\$O:z.//u,rƬih>ץKsHGc~js߹5p:U@|s)Pc<0Z@0 8wrumK*` p{N[mJ]ِi(R  gCO/A(Pne$nnnm`HU (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP ĹBUU_׿=ؿǚ۞z@yzxx9h(l T!s ԙS (l #P""""rkn{yu?H""""rqJ:#ǚ۞z@y:RΦ@9%""""ȱ涧+Pg^N$""""G)P#P?яBUU|2<<<> ?яG=Zj Ϟ=kaʫW›7ovcYV=CS? Ϟ= }QxyCUUŋ?}&S[χ~v~m5/^ϟ]Ϥ1M=o^^/O}^͟/_Cۜ y=͗/_juIȹXsS3/Pm;'|(y&<{,TUhGs"v$%51cDX/9!ˉϱ~7o<сUj7jN8,' %w qל'$}߸8-r9f~QUUO}kgHŋGG(nvݶ}˗OXsS3/P];y< ŋ 'nnB:a܄y:!C˘Sƌm൝ֶ Ƶm_O,ߩ#e]N-wqTjcǟf_+P85@sa9x T'v RTKn3}IJv'5OzRϝ<-':gʤjR>YcJ&ϻB x>cǾmW^=>m0=P]kj)""y9V*`^r&֋O=IׯWcG4Ni~/-ZږǕz׾ TRrcǸmzl3r'˦C>|}{)ϟ?rDw_B8ؘw *wt ȸkn{yu*gg^Mݳg:V}P >{Qem._%*.9yԘ14?~߶2NC?f_xd^>yRN+ܛ RSL+u5t_r."!"2<ǚ*P T/_&(zd~fh֕zs[Lu:S˩O>ytϓۦ@s /^=ԷCnWU裏³g³gm '|#-zS>ǾvZv9Br?^zzio׮-orsa9x ԩD:x IDATr8ˬ+kkn@0s/P]G"DD͛7N;ģm]&""9x ԩD<ӼKIDdBRΦ@9%""""ȱ涧+Pg^N$""""G)P@1r ԙS (l #P""""rkn{yu?H""""rqJ:#ǚ۞z@#ʿ_׿=ԿUu& ΅U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 Tx TUUOwExrsuss "܄v;ַݾ^(P ](P!]!H7~,%Oooo'=>Bwww盻Cүv žFuS_/ݥ@0w@@ym۰X,&-,5 SjSKiA(P.PǵX,BUUz)u*yQ }/< k݆efn"s+2TGˍ65xpqq6ͣSyNCj귧Nޯ׫9m8W|LvM TS7_JjJͯ7MUUr>AOՊ_V*ľ8yn˭KqUUk{ n6lBUUs9eo]> %0/c TP3:1dͯϙ\%5{Y6n̋Ţ=[]뮟z󚵽3w(P Tj@MbާҼ}j]^zcR_V6}cIaXJT\OBzUj{-yX,j :E}eb~sJ*@ h=]WRZKm]o~nUjXn士絍ml6p{{+ZzZkzCx{k{nu777čW^ܫ)Qp>(ES.Q3Eȡ@)P -G!쎶b7ֶz CR(F}tx!!:QmWtKR(Ȥ@)P dR( 2)P (JL @@&JR @)P{(@)P/Sه(@)P/Sه(@)P/Sه(@)P/Sه(@]z-gzy,g2})P T*l GYCP2JmrNyR84%S(tr/Sه(@MMu=2s֑_j}ϳ9Yw52})P TjHyw㺾{|򧌩 u2})P l TNy*)rrӷb4I_P2JE-Ose3(P 5#&Lei(J_4 @͈/Sه`J*@UU̹y^&Lei(w͝šه`JR @qh!FR/Pm;|L~>(P , T*Uvmmms66e*L@)P(P~mv[ߺږWr/aT!FR.P9)0C[Ȇcl2e*L@)P.PcN~׿]cRdT!FRΪ@M=}o9CQ}(>(P Tj{M)PͯǖcbT!FR,P}Hݯur\"u<&E&Lei(E/Sه`JRf䗩C0@)P3bT!FR1e*L@)P Ԍ2}Q(jF)P (JL @@&JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)P{(@)P/Sه(@)P/Sه(@)P/Sه(@)P/Sه(@_zʐz2}(P T*p]_s: f$ uJ:,CPJ*@֗;r/Sه(@ͮ@qK_U]{/֘e=Ͼ5=6w5M~>@I(j*gnu}׷q-][~ۺږWr/aT!J@)PE’[r3t-{m}Epc䗩CDRfS_==򒻬~׿mɹORL~>@I(j}Qu w)-gQuu1e*%Qb Ԕ4-+뱏MhJj~=t5/Sه(@YG|&}z\֟z}Yn{)g/Sه(@Ye~\ǻ䗩CDRξ@n</Sه(@jiyC֣D=fT!J@)Pg_8-_PJR8(_PJR8>x-29P JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dRȜ@)P/P!o9(P @<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`.ﶋpqq>&TUE vo}K^mfZr WWWp Tx TaWRn5K@ɓI>]*knmQ+Mbu1=vŤefA}JyQc9v ̟U yZ,#c=:s7ͣyQ Ĝ ԿrPR;\NzT<ݭyv ӧl6a\&1"O˽|xasq]cIG O&m;i{݇ 2U V~Ip]Iݷf \.w'j\"N웏v۹ܺWUU9ϩy f &TU.//;ǛSz777WܖuR|zն۬l#"""KP Tco}=~!]e6_?JR?ʖVmhxDrcq[~]<\__?:5c{]__e;U vTdJwO{S;r9|z8r[oz~ti:YA@hƐu7n^b@(wYƬwΉšه(@Ͷ@c9\)P})P t:9䗩CLRΦ@Ok{Lu{s9H/̾Ǭ;L~>@(5gSU↌qJRL~>@(j6*< EW[NN1{/Sه(@͢@喧rԌ}2RR:rۇ)_P2J:5Gƞ3eZϾ `j]]L~>@(^}֑zNmf)|Yw䗩CLR/P}7'}ƥ{|ݯ9=j5dm=/ه(@]_P2JR+_P2JR+_P2JR+_P2JR+_P2JRث>x-29P*JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dR(jF)P 5#&Lei(J_4 @͈/Sه`JRf䗩C0@_J&Lei(j{?rݶ޶Ƕm2}QY܂S]oo]m+I0e*L@)PEu-dC162}QY1~߮ )X}j2e*L@)PgU׷(> bi(5{cK1w1e*L@)PEFWo9C.JmcS"_4 Ud"䗩C0@)P3bT!FR1e*L@)P Ԍ2}Q(jFL~>(P 5#}Zdr(JL @@&JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(^LBR(䗩CDR(䗩CDR(䗩CDR(䗩CDR/PUU= ey=L~>@I(w9CPJ:lšه(@_RtX9䗩CDRfW U8ޯk̲ڞgK͚cn{&Le$ 53ُ_7o>][W۸sƖ{߮-m]m+I0e*%Q T_a- 9RBe匽붾"8CdT!J@)P)PͯUYF}y]V~߶'{)&Le$ 5Uf?(Pߺy۔3(^2}(P TjJRXǦk4@5[䗩CDR,P#>] =]V{}O=,y=䔳䗩CDR,P2t}]eT!J@)Pg_N7S䗩CDRމ5!Q3e*%Q/P/Sه(@)P/Sه(@)P{(@)PIR(Ȥ@)P dR( 2)P (JL @@&JR @)PIR(Ȥ@)P dR( 2)P TWDDDDdQBͷ_E( U TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP Pm/W×_|v|O:~!|{H TP_4Y?P? ï,|_%(U (|C?߅_9߅p U (|C???#]WON@0 <_m?^}=߅WSo~b)P B(_>/w}7@ ꫰}A*` @yb_odzϯMˇ_\@0 <@?YI<6^7| @;A(Py[b7/-{Y7|"|Z@0 ]U:(P B(ϯ"> ?_7_o~<'WmO@0 <>w?_g_ ó~ӇR PoGOBg?X0:|7R @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U (A(P0 TP`@<(P ByP @0 A*` ̃U NYDDDDDdXN=WDDDDDDfJDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""JDDDDD$3 Hf((P""""""QDDDDDD2@dFɌ%"""""`5ZIENDB`jasypt-jasypt-1.9.3/jasypt-dist/src/site/site.xml000066400000000000000000000112571360667575700220760ustar00rootroot00000000000000 Jasypt: Java simplified encryption images/jasypt-small.png http://www.jasypt.org/ org.apache.maven.skins maven-default-skin jasypt-jasypt-1.9.3/jasypt-dist/src/site/xdoc/000077500000000000000000000000001360667575700213375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-dist/src/site/xdoc/howtoencryptuserpasswords.xml000066400000000000000000000557251360667575700275110ustar00rootroot00000000000000 How to encrypt user passwords Daniel Fernandez
by Daniel Fernandez <dfernandez AT users.sourceforge.net>

Almost all modern web applications need, in one way or another, to encrypt their users' passwords. We could say that, from the moment that an application has users, and users sign in using a password, these passwords have to be stored in an encrypted way.

There are some intuitive reasons for this: our data stores can be compromised, and so can our communications. But the most important reason is that we have to think of our users' passwords as sensitive personal data. Their passwords are their key to their privacy, so they are personal, they are sensitive, and no one (not even us) has the right to know them. And we must honor this if we want to gain our user's trust.

So, we have to encrypt passwords, but... how? Here comes our first rule:

I. Encrypt passwords using one-way techniques, this is, digests.

This is because, except for some specific scenarios (mainly regarding legacy integration), there is absolutely no reason for a password being decrypted. If you encrypt your passwords using password-based encryption (a two-way technique) and an attacker gets to know your encryption password, all of your user passwords will be revealed (and, probably, all at a time). If you don't have such encryption password (or key) to be able to decrypt, this risk disappears, and the attacker will have to trust on brute force or similar strategies.

'But what if one of my users loses his/her password? Can't I remind it to him/her?'

The answer is a loud and clear NO. Not only you cannot do such a thing as reminding their passwords to them, but in fact you should not even have a way to get to read/know/see your users' passwords, no matter if you are the system administrator! If one of your users loses his/her password, just reset it to a new value and send him/her a message to a verified email address with the new one, asking to change it as soon as possible.

Now that it is clear that password digesting is a must, which digest algorithm should we use? Well, there are several, and it largely depends on your needs. The most used ones are:

  • MD5 algorithm

  • SHA family: SHA-1 algorithm and SHA-2 variants (SHA-224, SHA-256, SHA-384 and SHA-512)

In most cases, both MD5 or SHA-1 will be adequate choices for password digesting, although applying these algorithms will not be enough, as we will see later on.

When we are told that we should use digests for password encryption, and given that digests are one-way techniques, the next question that arises to our minds usually is: 'If I cannot decrypt passwords... how will I check if my users entered the right one?'

There is a very simple answer to this question, which we will adopt as our second rule:

II. Match input and stored passwords by comparing digests, not unencrypted strings.

Which means that, once our users have entered their passwords at sign in, we will digest their input with the same algorithm we have previously used when storing the password, and then compare both digests. As digest algorithms guarantee that two equal inputs will get equal digests (which is not true in the opposite direction), if digests match we can then consider the password input by the user as valid.

All the digest algorithms (also cryptographic hash functions) mentioned above share a feature: they are public. They are well-known and largely implemented algorithms, and so anyone can use them, and not only us.

If anyone can use the same algorithm that we use, and for some reason attackers get to see our database of password digests, how can we be sure that they will not be able to guess some of our user passwords by simply trying all the possibilities until they find one which digest matches the stored one (brute force)?

Well, the answer is... we cannot. But we can make this such an overwhelming and time-consuming task that they will not want to, unless they can wait for eternity. For achieving this, two concepts come in our help: the salt and the iteration count.

3.1. The salt

The salt is a sequence of bytes that is added to the password before being digested. This makes our digests different to what they would be if we encrypted the password alone, and as a result protects us against dictionary attacks. We can adopt two different strategies regarding salt:

  • Use a fixed salt, a sequence of bytes that we will use for digesting every password. We can keep this salt hidden and consider it an added security value, but it can make our system more vulnerable to birthday attacks and, in general, attacks driven against our database of passwords as a whole.

  • Use a variable salt, which is usually a safer option (better if it is random). This is generated or computed separately for each password being digested and it allows each stored password to be decoupled from the others, creating a stronger overall protection and highly improving safety for attacks driven against our database of passwords as a whole.

In practice, random (or at least variable) salt is a much better idea because, although its being random will force us to store it unencrypted along with the digest (so that we can recover it) and this will make it trivial for an attacker to know it, it will still let each of our users' passwords remain decoupled from the rest, so that they will have to be attacked separately.

Think that, if we use a fixed salt and the attacker gets to know this fixed salt, the security of the whole database of passwords will be dramatically decreased. And there are several ways an attacker can get to know this salt, like applying brute force on his own password or on a password he/she has got somehow from a valid user. In a fixed-salt scenario, a weak user could lead us to a weak overall password system.

Nevertheless, if still you want to keep some part of the salt secret, a good approach could be a mix of both techniques, using a salt composed of both a fixed secret portion and a random one, with only the random bytes being stored undigested along with the digest result.

The minimum recommended size of salt is 8 bytes. If a mixed approach is used, at least 8 of its bytes should be random. This said, we can state our third rule:

III. Use a salt containing at least 8 random bytes, and attach these random bytes, undigested, to the result.

3.2. The iteration count

The iteration count refers to the number of times that the hash function with which we are digesting is applied to its own results.

This means that, once we have selected a salt and concatenated the password to it, we will have to apply the hash function (say, an MD5 algorithm), get the result, and then pass it again as input to the same hash function, then do the same again and again and again... a number of times.

The minimum recommended number of iterations is 1,000, and it will provide us with a good amount of extra security. Think that, when you are creating a single password digest for a new user, the difference between applying the hash function once or a thousand times won't be a problem for you, maybe a couple hundreds of milliseconds... but attackers would have to generate an enormous amount of tentative password digests when brute-forcing and, for an attacker, the difference between applying the hash function once and applying it a thousand times for each try would be a real computational problem.

So, it seems that we have a fourth rule:

IV. Iterate the hash function at least 1,000 times.

3.3. Put graphically

We can represent this whole process of using a salt and an iteration count graphically as this:

Password encryption process

Before being able of correctly storing our password digests, there still is something that we should care about, which is the mismatch between character strings and byte sequences: two identical character strings may be represented with different byte sequences depending on the encoding being applied for translation (ISO-8859-1, UTF-8, etc...).

This will affect us because passwords are usually input by users as character strings, but digest algorithms work at a byte level.

4.1. Troubleshooting encoding at password input

Imagine that a new user signs up with a password containing a non-ASCII character, and your sign-up application, running on a Windows 2000 machine in Western Europe, converts the input character string to bytes without choosing a specific encoding for the operation, and thus using the default one, which in that Windows system would be ISO-8859-1. The sign-up logic digests the resulting bytes and the password gets stored.

Then, this user comes around again and this time he/she does not visit your sign-up application, but instead some other app running on the same password database but on a Linux machine. The user correctly inputs his/her password and... they don't match!

Why? because most Linux systems use UTF-8 as a default encoding, and thus the passwords input by the user in the two different scenarios have been translated into different byte sequences by each of the machines, affecting correct password matching.

How to solve this: by setting a fixed encoding for string-to-byte translations. Here comes rule number five:

V. Prior to digesting, perform string-to-byte sequence translation using a fixed encoding, preferably UTF-8.

If you are using Java, where String objects are encoding-independent (although backed by UTF-16), you won't have to worry whether your application uses ISO-8859-1 or any other encoding instead of UTF-8 for its user interface, as will not be necessary that the encoding for password digesting matches that of the user interface. It is just necessary that this encoding be a fixed one, and UTF-8 will bring you the right balance between size and charset completeness (Unicode).

Also, you should care about Unicode Normalization, as depending on the input system, you could get different character sequences (and thus byte sequences) for the same unicode visual character representation. A normalization operation which makes sure your code is in NFC form may be necessary here. For more information on Unicode normalization, see this issue of Core Java Technologies Tech Tips.

4.2. Troubleshooting encoding at digest storage

We will normally want to manage and store the digested password as a character string, but the digest function will output a sequence of bytes which will not necessarily represent a valid character string in any encoding. So, translating our digested byte sequence back into a character string could not be possible, and we could risk data loss when doing it.

This is where BASE64 encoding comes to the rescue. By encoding our digested sequence of bytes in BASE64, we will make sure that the output byte sequence represents a valid, displayable, US-ASCII character string. So we will be able to safely translate the BASE64-encoded byte sequence into a character string specifying US-ASCII as the encoding.

VI. Finally, apply BASE64 encoding and store the digest as an US-ASCII character string.

As an alternative to BASE64, you could also encode your output as hexadecimal strings, which would be an equally valid method (although you would get more lengthy digest strings).

We now have a complete list of rules to be applied:

I. Encrypt passwords using one-way techniques, this is, digests.

II. Match input and stored passwords by comparing digests, not unencrypted strings.

III. Use a salt containing at least 8 random bytes, and attach these random bytes, undigested, to the result.

IV. Iterate the hash function at least 1,000 times.

V. Prior to digesting, perform string-to-byte sequence translation using a fixed encoding, preferably UTF-8.

VI. Finally, apply BASE64 encoding and store the digest as an US-ASCII character string.

The easiest way of encrypting passwords in Java using the explained techniques is using Jasypt, which already does all this processing transparently for you.

If we cannot use jasypt, or if for some reason we wish to develop encryption features ourselves, we will need the following tools for our task:

  • java.security.MessageDigest for creating digests. This class allows to specify the digest algorithm we wish to use.

  • java.security.SecureRandom for generating random salt in a secure manner, using algorithms like SHA1PRNG.

  • The java.lang.String.getBytes(String charsetName) method, for obtaining a byte sequence from the input String, specifying a fixed encoding ("UTF-8").

  • org.apache.commons.codec.binary.Base64, part of the Apache Commons-Codec library, for performing BASE64 translations on hash output.

  • java.text.Normalizer (only in Java SE 6) or com.ibm.icu.text.Normalizer (part of the International Components for Unicode package), for Unicode normalization operations.

Also, the source code for classes org.jasypt.digest.StandardByteDigester and org.jasypt.digest.StandardStringDigester, available at the Source Repository, can be used as a guide.

7.1. Brute force attacks

Performed on: A single user password.

Description: The attacker tries to get the user's password by exhaustively generating all possible passwords, digesting them and testing if they match with the user's password digest. Learn more [wikipedia.org].

Our defense: By iterating the hash function to a number like 1,000 (minimum recommended), the overhead of password digest creation for the user at sign-up or sign-in time is not significant, but the accumulated cost for a brute force attacker generating millions of digests will be very considerable. Remember that one of the best ways to protect your encrypted data is making the cost of breaking your security too high to be worth the effort.

7.2. Dictionary attacks

Performed on: Either a single user password or a database of user passwords as a whole.

Description: The attacker tries to get the user's password by matching its digest against a set of "most possible" password digests, typically generated from a list of words in a dictionary. This attack exploits a severe weakness in nowadays applications, as an important amount of users set a dictionary word as their password. Learn more [wikipedia.org].

Our defense: By adding a random salt, the weakness of the dictionary-based passwords many people use is reduced (they are no longer dictionary words), and the possibility of the digest appearing on a set of digests previously created by the attacker is minimal.

7.3. Birthday attacks

Performed on: Database of user passwords as a whole.

Description: This attack exploits the Birthday paradox [wikipedia.org], which in brief states that, having a large set of user password digests, the probability of generating a password which digest collides with at least one of the digests in the set is very much higher than what you would intuitively expect. And this probability increases dramatically as the size of the set (the number of users) augments. Learn more [wikipedia.org].

Our defense: By adding a random salt the possibilities of a birthday attack to succeed are minimum, because the attacker would have to attack each password separately, and not the set of passwords as a whole, to find a collision. This is because he/she would have to find a password that creates the same digest as the attacked one using the same salt which was used for digesting it, which is different for each password (this is, it would become a brute force attack).

jasypt-jasypt-1.9.3/jasypt-hibernate3/000077500000000000000000000000001360667575700177305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/.gitignore000066400000000000000000000000721360667575700217170ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-hibernate3/BUILD.txt000066400000000000000000000015111360667575700213260ustar00rootroot00000000000000 Building JASYPT-HIBERNATE3 -------------------------- To build JASYPT-HIBERNATE3 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-HIBERNATE3 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-hibernate3-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-hibernate3/{version}/jasypt-hibernate3-{version}.jar Generating Javadoc for JASYPT-HIBERNATE3 ---------------------------------------- If you wish to generate the javadoc for JASYPT-HIBERNATE3, execute this from the JASYPT-HIBERNATE3 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-hibernate3/ChangeLog.txt000066400000000000000000000007441360667575700223250ustar00rootroot000000000000001.9.3 ===== - Fixed #32: encryption works but decryption does not, Java 8 (JCE jars installed). Added support for initialization vectors needed for AES encryption and decryption since Java 8. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-hibernate3 package from previous monolithic jasypt module. - Renamed org.jasypt.hibernate package as org.jasypt.hibernate3, and deprecated the classes in the old package. - Created additional tests jasypt-jasypt-1.9.3/jasypt-hibernate3/LICENSE.txt000066400000000000000000000261361360667575700215630ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-hibernate3/NOTICE.txt000066400000000000000000000072671360667575700214660ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-hibernate3/README.txt000066400000000000000000000006111360667575700214240ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-hibernate3/RELEASING.txt000066400000000000000000000023061360667575700220030ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-hibernate3/USAGE.txt000066400000000000000000000012041360667575700213320ustar00rootroot00000000000000 Using JASYPT-HIBERNATE3 from Maven 2 ------------------------------------ In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-hibernate3 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-hibernate3/pom.xml000066400000000000000000000213001360667575700212410ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-hibernate3 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true jboss-nexus-repository JBoss Nexus Repository http://repository.jboss.org/nexus/content/groups/public-jboss/ src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/java ** **/*.java src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.1 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.hibernate hibernate 3.0 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test commons-logging commons-logging 1.1.1 test dom4j dom4j 1.6.1 test commons-collections commons-collections 3.1 test net.sf.ehcache ehcache 1.2 test cglib cglib 2.1_3 test javax.transaction jta 1.0.1B test org.hsqldb hsqldb 2.2.6 test jasypt-jasypt-1.9.3/jasypt-hibernate3/src/000077500000000000000000000000001360667575700205175ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/000077500000000000000000000000001360667575700214435ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/000077500000000000000000000000001360667575700223645ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/000077500000000000000000000000001360667575700231535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/000077500000000000000000000000001360667575700244655ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/000077500000000000000000000000001360667575700264265ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/connectionprovider/000077500000000000000000000000001360667575700323405ustar00rootroot00000000000000EncryptedPasswordC3P0ConnectionProvider.java000066400000000000000000000130501360667575700427240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.connectionprovider; import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.connection.C3P0ConnectionProvider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link C3P0ConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordC3P0ConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="c3p0.min_size">5</property>
 *      <property name="c3p0.max_size">20</property>
 *      <property name="c3p0.timeout">1800</property>
 *      <property name="c3p0.max_statements">50</property>
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.4 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedPasswordC3P0ConnectionProvider extends C3P0ConnectionProvider { public EncryptedPasswordC3P0ConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(Environment.DRIVER); final String url = props.getProperty(Environment.URL); final String user = props.getProperty(Environment.USER); final String password = props.getProperty(Environment.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( Environment.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( Environment.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( Environment.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( Environment.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate do the rest super.configure(props); } } EncryptedPasswordDriverManagerConnectionProvider.java000066400000000000000000000126651360667575700450200ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.connectionprovider; import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.connection.DriverManagerConnectionProvider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link DriverManagerConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      <!-- Database connection settings -->
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="connection.pool_size">5</property>
 *      
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.4 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedPasswordDriverManagerConnectionProvider extends DriverManagerConnectionProvider { public EncryptedPasswordDriverManagerConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(Environment.DRIVER); final String url = props.getProperty(Environment.URL); final String user = props.getProperty(Environment.USER); final String password = props.getProperty(Environment.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( Environment.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( Environment.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( Environment.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( Environment.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate process super.configure(props); } } ParameterNaming.java000066400000000000000000000034121360667575700361760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.connectionprovider; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; /** *

* Constant names of the parameters that can be used by a jasypt's * Hibernate connection provider. *

* * @since 1.4 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class ParameterNaming { /** * Property in hibernate.cfg.xml or * hibernate.properties which contains the registered name * (in {@link HibernatePBEEncryptorRegistry}) of the encryptor which * will be used to decrypt the datasource parameters. */ public static final String ENCRYPTOR_REGISTERED_NAME = "hibernate.connection.encryptor_registered_name"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/000077500000000000000000000000001360667575700304535ustar00rootroot00000000000000HibernatePBEBigDecimalEncryptor.java000066400000000000000000000317521360667575700373060ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.encryptor; import java.math.BigDecimal; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigDecimalEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigDecimalEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigDecimalEncryptor be explicitly set * with {@link #setEncryptor(PBEBigDecimalEncryptor)}. If not, a * StandardPBEBigDecimalEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigDecimalEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigDecimalEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigDecimalEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigDecimalEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigDecimalEncryptor * objects this way to wrap PBEBigDecimalEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigDecimalEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class HibernatePBEBigDecimalEncryptor { private String registeredName = null; private PBEBigDecimalEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigDecimalEncryptor It also * creates a StandardPBEBigDecimalEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigDecimalEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigDecimalEncryptor * is registered programmatically. */ HibernatePBEBigDecimalEncryptor(final String registeredName, final PBEBigDecimalEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigDecimalEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigDecimalEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigDecimalEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigDecimal encrypt(final BigDecimal message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigDecimal decrypt(final BigDecimal encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigDecimalEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigDecimalEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEBigIntegerEncryptor.java000066400000000000000000000316611360667575700373440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.encryptor; import java.math.BigInteger; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigIntegerEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigIntegerEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigIntegerEncryptor be explicitly set * with {@link #setEncryptor(PBEBigIntegerEncryptor)}. If not, a * StandardPBEBigIntegerEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigIntegerEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigIntegerEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigIntegerEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigIntegerEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigIntegerEncryptor * objects this way to wrap PBEBigIntegerEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigIntegerEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class HibernatePBEBigIntegerEncryptor { private String registeredName = null; private PBEBigIntegerEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigIntegerEncryptor It also * creates a StandardPBEBigIntegerEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigIntegerEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigIntegerEncryptor * is registered programmatically. */ HibernatePBEBigIntegerEncryptor(final String registeredName, final PBEBigIntegerEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigIntegerEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigIntegerEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigIntegerEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigInteger encrypt(final BigInteger message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigInteger decrypt(final BigInteger encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigIntegerEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigIntegerEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEByteEncryptor.java000066400000000000000000000310721360667575700362240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.encryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEByteEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEByteEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEByteEncryptor be explicitly set * with {@link #setEncryptor(PBEByteEncryptor)}. If not, a * StandardPBEByteEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="byteEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEByteEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEByteEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateByteEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="byteEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEByteEncryptor * objects this way to wrap PBEByteEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEByteEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class HibernatePBEByteEncryptor { private String registeredName = null; private PBEByteEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEByteEncryptor It also * creates a StandardPBEByteEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEByteEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEByteEncryptor * is registered programmatically. */ HibernatePBEByteEncryptor(final String registeredName, final PBEByteEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEByteEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEByteEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEByteEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public byte[] encrypt(final byte[] message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public byte[] decrypt(final byte[] encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEByteEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEByteEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEEncryptorRegistry.java000066400000000000000000000270021360667575700371270ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.encryptor; import java.util.HashMap; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Registry for all the PBE*Encryptor which are eligible for * use from Hibernate. *

*

* This class is intended to be directly used in applications where * an IoC container (like Spring Framework) is not present. If it is, * it is better to use the HibernatePBE*Encryptor classes * directly, instead. *

*

* This registry is a singleton which maintains a registry * of PBE*Encryptor objects which can be used from Hibernate, * by using its registeredName to reference them from mappings. *

*

* The steps would be: *

    *
  1. Obtain the registry instance ({@link #getInstance()}).
  2. *
  3. Register the encryptor, giving it a registered name * (registerPBE*Encryptor(String, PBE*Encryptor).
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * when registering the encryptor.
  6. *
*

*

* This is, first register the encryptor (example with a String encryptor): *

*

*

 *  StandardPBEStringEncryptor myEncryptor = new StandardPBEStringEncryptor();
 *  ...
 *  HibernatePBEEncryptorRegistry registry =
 *      HibernatePBEEncryptorRegistry.getInstance();
 *  registry.registerPBEStringEncryptor("myHibernateEncryptor", myEncryptor);
 * 
*

*

* And then, reference it from a Hibernate mapping file: *

*

*

 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateEncryptor</param>
 *    </typedef>
 * 
*

* * * @since 1.2 (class existed as * org.jasypt.hibernate.HibernatePBEEncryptorRegistry since 1.0) * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class HibernatePBEEncryptorRegistry { // The singleton instance private static final HibernatePBEEncryptorRegistry instance = new HibernatePBEEncryptorRegistry(); // Registry maps private final HashMap stringEncryptors = new HashMap(); private final HashMap bigIntegerEncryptors = new HashMap(); private final HashMap bigDecimalEncryptors = new HashMap(); private final HashMap byteEncryptors = new HashMap(); /** * Returns the singleton instance of the registry. * * @return the registry. */ public static HibernatePBEEncryptorRegistry getInstance() { return instance; } // The registry cannot be externally instantiated. private HibernatePBEEncryptorRegistry() { super(); } /** * Registers a PBEStringEncryptor object with the specified * name. * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEStringEncryptor( final String registeredName, final PBEStringEncryptor encryptor) { final HibernatePBEStringEncryptor hibernateEncryptor = new HibernatePBEStringEncryptor(registeredName, encryptor); this.stringEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void registerHibernatePBEStringEncryptor( final HibernatePBEStringEncryptor hibernateEncryptor) { this.stringEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEStringEncryptor(final String name) { this.stringEncryptors.remove(name); } /** * Returns the PBEStringEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEStringEncryptor getPBEStringEncryptor( final String registeredName) { final HibernatePBEStringEncryptor hibernateEncryptor = (HibernatePBEStringEncryptor) this.stringEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigIntegerEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigIntegerEncryptor( final String registeredName, final PBEBigIntegerEncryptor encryptor) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = new HibernatePBEBigIntegerEncryptor(registeredName, encryptor); this.bigIntegerEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigIntegerEncryptor( final HibernatePBEBigIntegerEncryptor hibernateEncryptor) { this.bigIntegerEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigIntegerEncryptor(final String name) { this.bigIntegerEncryptors.remove(name); } /** * Returns the PBEBigIntegerEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigIntegerEncryptor getPBEBigIntegerEncryptor( final String registeredName) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = (HibernatePBEBigIntegerEncryptor) this.bigIntegerEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigDecimalEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigDecimalEncryptor( final String registeredName, final PBEBigDecimalEncryptor encryptor) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = new HibernatePBEBigDecimalEncryptor(registeredName, encryptor); this.bigDecimalEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigDecimalEncryptor( final HibernatePBEBigDecimalEncryptor hibernateEncryptor) { this.bigDecimalEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigDecimalEncryptor(final String name) { this.bigDecimalEncryptors.remove(name); } /** * Returns the PBEBigDecimalEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigDecimalEncryptor getPBEBigDecimalEncryptor( final String registeredName) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = (HibernatePBEBigDecimalEncryptor) this.bigDecimalEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEByteEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEByteEncryptor( final String registeredName, final PBEByteEncryptor encryptor) { final HibernatePBEByteEncryptor hibernateEncryptor = new HibernatePBEByteEncryptor(registeredName, encryptor); this.byteEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void registerHibernatePBEByteEncryptor( final HibernatePBEByteEncryptor hibernateEncryptor) { this.byteEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEByteEncryptor(final String name) { this.byteEncryptors.remove(name); } /** * Returns the PBEByteEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEByteEncryptor getPBEByteEncryptor( final String registeredName) { final HibernatePBEByteEncryptor hibernateEncryptor = (HibernatePBEByteEncryptor) this.byteEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } } HibernatePBEStringEncryptor.java000066400000000000000000000363471360667575700366010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.encryptor; import java.security.Provider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEStringEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEStringEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEStringEncryptor be explicitly set * with {@link #setEncryptor(PBEStringEncryptor)}. If not, a * StandardPBEStringEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setProviderName(String)}, * {@link #setProvider(Provider)}, {@link #setStringOutputType(String)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="stringEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateStringEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="stringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEStringEncryptor * objects this way to wrap PBEStringEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEStringEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.2 (substitutes org.jasypt.hibernate.HibernatePBEEncryptor which * existed since 1.0) * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class HibernatePBEStringEncryptor { private String registeredName = null; private PBEStringEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEStringEncryptor. It also * creates a StandardPBEStringEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEStringEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEStringEncryptor * is registered programmatically. */ HibernatePBEStringEncryptor(final String registeredName, final PBEStringEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public synchronized PBEStringEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEStringEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public synchronized void setEncryptor(final PBEStringEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the name of the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param providerName the name of the JCE provider (already registered) */ public void setProviderName(final String providerName) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProviderName(providerName); } /** * Sets the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param provider the JCE provider to be used */ public void setProvider(final Provider provider) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProvider(provider); } /** * Sets the type of String output ("base64" (default), "hexadecimal") to * be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param stringOutputType the type of String output */ public void setStringOutputType(final String stringOutputType) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setStringOutputType(stringOutputType); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public String encrypt(final String message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public String decrypt(final String encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEStringEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEStringEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/000077500000000000000000000000001360667575700274075ustar00rootroot00000000000000AbstractEncryptedAsStringType.java000066400000000000000000000234511360667575700361360ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; /** * * Base class for Hibernate UserTypes to store * values as encrypted strings. * * @since 1.2 * @author Daniel Fernández * @author Iván García Sáinz-Aja * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public abstract class AbstractEncryptedAsStringType implements UserType, ParameterizedType { static final int sqlType = Types.VARCHAR; static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String providerName = null; private String password = null; private Integer keyObtentionIterations = null; private String stringOutputType = null; protected PBEStringEncryptor encryptor = null; /** * Converts given String to its Object form. * @param string the string value * @return the object form of the passed String */ protected abstract Object convertToObject(final String string); /** * Converts given Object to its String form. * @param object the object value * @return the string form of the passes Object */ protected String convertToString(final Object object) { return object == null? null : object.toString(); } public final int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public abstract Class returnedClass(); public final boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public final Object deepCopy(final Object value) throws HibernateException { return value; } public final Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public final Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public final boolean isMutable() { return false; } public final int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public final Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public final Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final String message = rs.getString(names[0]); return rs.wasNull() ? null : convertToObject(this.encryptor.decrypt(message)); } public final void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { st.setString(index, this.encryptor.encrypt(convertToString(value))); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramProviderName = parameters.getProperty(ParameterNaming.PROVIDER_NAME); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramStringOutputType = parameters.getProperty(ParameterNaming.STRING_OUTPUT_TYPE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramProviderName != null) { this.providerName = paramProviderName; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } if (paramStringOutputType != null) { this.stringOutputType = paramStringOutputType; } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } protected synchronized final void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor pbeEncryptor = registry.getPBEStringEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEStringEncryptor newEncryptor = new StandardPBEStringEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.providerName != null) { newEncryptor.setProviderName(this.providerName); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } if (this.stringOutputType != null) { newEncryptor.setStringOutputType(this.stringOutputType); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigDecimalAsStringType.java000066400000000000000000000100221360667575700363410ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.math.BigDecimal; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigDecimal values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBigDecimalAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigDecimal(string); } public Class returnedClass() { return BigDecimal.class; } } EncryptedBigDecimalType.java000066400000000000000000000322501360667575700346750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.io.Serializable; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEBigDecimalEncryptor; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigDecimal values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigDecimalEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigDecimalEncryptor (see * {@link HibernatePBEBigDecimalEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

*

* About the decimalScale parameter *

* The decimalScale parameter is aimed at setting the scale with which * BigDecimal numbers will be set to and retrieved from the database. It is * an important parameter because many DBMSs return BigDecimal numbers with * a scale equal to the amount of decimal positions declared for the field * (e.g. if we store "18.23" (scale=2) in a DECIMAL(15,5) field, we can get a * "18.23000" (scale=5) back when we retrieve the number). This can affect * correct decryption of encrypted numbers, but specifying a * decimalScale parameter will solve this issue. *

*

* So, if we set decimalScale to 3, and we store "18.23", this * Hibernate type will send "18.230" to the encryptor, which is the value that * we will get back from the database at retrieval time (a scale of "3" * will be set again on the value obtained from DB). If it is necessary, a * DOWN rounding operation is executed on the number. *

*
*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBigDecimalType implements UserType, ParameterizedType { private static final int sqlType = Types.NUMERIC; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private Integer decimalScale = null; private PBEBigDecimalEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigDecimal.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal storedEncryptedMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigDecimal scaledEncryptedMessage = storedEncryptedMessage.setScale( this.decimalScale.intValue(), BigDecimal.ROUND_UNNECESSARY); return this.encryptor.decrypt(scaledEncryptedMessage); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigDecimal scaledValue = ((BigDecimal) value).setScale( this.decimalScale.intValue(), BigDecimal.ROUND_DOWN); final BigDecimal encryptedMessage = this.encryptor.encrypt(scaledValue); st.setBigDecimal(index, encryptedMessage); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramDecimalScale = parameters.getProperty(ParameterNaming.DECIMAL_SCALE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } if (paramDecimalScale != null) { try { this.decimalScale = new Integer(Integer.parseInt(paramDecimalScale)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.DECIMAL_SCALE + "\" is not a valid integer"); } } else { throw new EncryptionInitializationException( ParameterNaming.DECIMAL_SCALE + " must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigDecimalEncryptor pbeEncryptor = registry.getPBEBigDecimalEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big decimal encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigDecimalEncryptor newEncryptor = new StandardPBEBigDecimalEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigIntegerAsStringType.java000066400000000000000000000100221360667575700364000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.math.BigInteger; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigInteger values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBigIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigInteger(string); } public Class returnedClass() { return BigInteger.class; } } EncryptedBigIntegerType.java000066400000000000000000000257721360667575700347470ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEBigIntegerEncryptor; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigInteger values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigIntegerEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigIntegerEncryptor (see * {@link HibernatePBEBigIntegerEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBigIntegerType implements UserType, ParameterizedType { private static int sqlType = Types.NUMERIC; private static int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEBigIntegerEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigInteger.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal decimalMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigInteger message = decimalMessage.setScale(0, BigDecimal.ROUND_UNNECESSARY). unscaledValue(); return this.encryptor.decrypt(message); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigInteger encryptedMessage = this.encryptor.encrypt((BigInteger) value); st.setBigDecimal(index, new BigDecimal(encryptedMessage)); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigIntegerEncryptor pbeEncryptor = registry.getPBEBigIntegerEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigIntegerEncryptor newEncryptor = new StandardPBEBigIntegerEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBinaryType.java000066400000000000000000000321351360667575700341430ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.cfg.Environment; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate.encryptor.HibernatePBEByteEncryptor; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of byte[] values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEByteEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateByteEncryptor (see * {@link HibernatePBEByteEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBinaryType implements UserType, ParameterizedType { private static final int BLOCK_SIZE = 2048; private static final int sqlType = Types.VARBINARY; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEByteEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return byte[].class; } public boolean equals(final Object x, final Object y) throws HibernateException { return (x == y) || (x != null && y != null && java.util.Arrays.equals((byte[]) x, (byte[]) y)); } public Object deepCopy(final Object value) throws HibernateException { if (value == null) { return null; } final byte[] valueBytes = (byte[]) value; final byte[] copyBytes = new byte[valueBytes.length]; System.arraycopy(valueBytes, 0, copyBytes, 0, valueBytes.length); return copyBytes; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return true; } public int hashCode(final Object x) throws HibernateException { final byte[] valueBytes = (byte[]) x; int result = 1; for (int i = 0; i < valueBytes.length; i++ ) { result = (result * 17) + valueBytes[i]; } return result; } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return (original == null)? null : deepCopy(original); } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); byte[] encryptedValue = null; if (Environment.useStreamsForBinary()) { final InputStream inputStream = rs.getBinaryStream(names[0]); if (rs.wasNull()) { return null; } final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BLOCK_SIZE); final byte[] inputBuff = new byte[BLOCK_SIZE]; try { int readBytes = 0; while (readBytes != -1) { readBytes = inputStream.read(inputBuff); if (readBytes != -1) { outputStream.write(inputBuff, 0, readBytes); } } } catch (IOException e) { throw new HibernateException( "IOException occurred reading a binary value", e); } finally { try { inputStream.close(); } catch (IOException e) { // exception ignored } try { outputStream.close(); } catch (IOException e) { // exception ignored } } encryptedValue = outputStream.toByteArray(); } else { encryptedValue = rs.getBytes(names[0]); if (rs.wasNull()) { return null; } } return this.encryptor.decrypt(encryptedValue); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final byte[] encryptedValue = this.encryptor.encrypt((byte[]) value); if (Environment.useStreamsForBinary()) { st.setBinaryStream( index, new ByteArrayInputStream(encryptedValue), encryptedValue.length); } else { st.setBytes(index, encryptedValue); } } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEByteEncryptor pbeEncryptor = registry.getPBEByteEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEByteEncryptor newEncryptor = new StandardPBEByteEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBooleanAsStringType.java000066400000000000000000000077361360667575700357620ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Boolean values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedBooleanAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return Boolean.valueOf(string); } public Class returnedClass() { return Boolean.class; } } EncryptedByteAsStringType.java000066400000000000000000000076751360667575700353100ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Byte values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedByteAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Byte(string); } public Class returnedClass() { return Byte.class; } } EncryptedCalendarAsStringType.java000066400000000000000000000136641360667575700361110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.util.Calendar; import java.util.Properties; import java.util.TimeZone; import org.jasypt.commons.CommonUtils; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Calendar values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* The boolean storeTimeZone parameter allows the Calendar to be * re-created with the same TimeZone that it was created. This is an * optional parameter, and its default value is FALSE. *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedCalendarAsStringType extends AbstractEncryptedAsStringType{ private Boolean storeTimeZone = Boolean.FALSE; /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final String[] stringTokens = CommonUtils.split(string); TimeZone tz = null; final long timeMillis = Long.valueOf(stringTokens[0]).longValue(); if (this.storeTimeZone.booleanValue()) { tz = TimeZone.getTimeZone(stringTokens[1]); } else { tz = TimeZone.getDefault(); } final Calendar cal = Calendar.getInstance(); cal.setTimeZone(tz); cal.setTimeInMillis(timeMillis); return cal; } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final StringBuffer strBuff = new StringBuffer(); final long timeMillis = ((Calendar) object).getTimeInMillis(); strBuff.append((new Long(timeMillis)).toString()); if (this.storeTimeZone.booleanValue()) { strBuff.append(" "); strBuff.append(((Calendar) object).getTimeZone().getID()); } return strBuff.toString(); } public synchronized void setParameterValues(final Properties parameters) { super.setParameterValues(parameters); final String paramStoreTimeZone = parameters.getProperty(ParameterNaming.STORE_TIME_ZONE); if ((paramStoreTimeZone != null) && (!paramStoreTimeZone.trim().equals(""))) { this.storeTimeZone = CommonUtils.getStandardBooleanValue(paramStoreTimeZone); } } public Class returnedClass() { return Calendar.class; } } EncryptedDateAsStringType.java000066400000000000000000000104671360667575700352530ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import java.util.Date; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Date values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedDateAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final long timeMillis = Long.valueOf(string).longValue(); return new Date(timeMillis); } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final long timeMillis = ((Date) object).getTime(); return String.valueOf(timeMillis); } public Class returnedClass() { return Date.class; } } EncryptedDoubleAsStringType.java000066400000000000000000000077211360667575700356070ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Double values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedDoubleAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Double(string); } public Class returnedClass() { return Double.class; } } EncryptedFloatAsStringType.java000066400000000000000000000077101360667575700354400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Float values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedFloatAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Float(string); } public Class returnedClass() { return Float.class; } } EncryptedIntegerAsStringType.java000066400000000000000000000077361360667575700360000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Integer values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Integer(string); } public Class returnedClass() { return Integer.class; } } EncryptedLongAsStringType.java000066400000000000000000000077001360667575700352710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Long values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedLongAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Long(string); } public Class returnedClass() { return Long.class; } } EncryptedShortAsStringType.java000066400000000000000000000077171360667575700355010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Short values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedShortAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Short(string); } public Class returnedClass() { return Short.class; } } EncryptedStringType.java000066400000000000000000000077371360667575700341770ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; import org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows transparent * encryption of String values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.2 (substitutes org.jasypt.hibernate.EncryptedTextType * which existed since 1.0) * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class EncryptedStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String stringValue) { return stringValue; } public Class returnedClass() { return String.class; } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate/type/ParameterNaming.java000066400000000000000000000066711360667575700333360ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate.type; /** *

* Constant names of the parameters that can be used by a jasypt type's * typedef declaration in a Hibernate mapping. *

* * @since 1.4 (was org.jasypt.hibernate.ParameterNaming since 1.0) * * @author Daniel Fernández * * @deprecated Will be removed in 1.11. Package org.jasypt.hibernate.connectionprovider * has been renamed as org.jasypt.hibernate3.connectionprovider. * */ public final class ParameterNaming { /** *

* The registered name of an encryptor previously registered at the * {@link org.jasypt.hibernate.encryptor.HibernatePBEEncryptorRegistry}. *

*

* Value = encryptorRegisteredName *

*/ public static final String ENCRYPTOR_NAME = "encryptorRegisteredName"; /** *

* The encryption algorithm. *

*

* Value = algorithm *

*/ public static final String ALGORITHM = "algorithm"; /** *

* The name of the JCE security provider we want to get the algorithm from * (if it is no the default one. *

*

* Value = providerName *

*/ public static final String PROVIDER_NAME = "providerName"; /** *

* The encryption password. *

*

* Value = password *

*/ public static final String PASSWORD = "password"; /** *

* The number of hashing iterations to be applied for obtaining the * encryption key. *

*

* Value = keyObtentionIterations *

*/ public static final String KEY_OBTENTION_ITERATIONS = "keyObtentionIterations"; /** *

* The type of String output ("base64" (default), "hexadecimal") to be * generated. *

*

* Value = stringOutputType *

*/ public static final String STRING_OUTPUT_TYPE = "stringOutputType"; /** *

* The scale (numbers after the decimal point) to be used when storing * decimal numbers. *

*

* Value = decimalScale *

*/ public static final String DECIMAL_SCALE = "decimalScale"; /** *

* Whether the calendar time zone should be stored with the date or not. *

*

* Value = storeTimeZone *

*/ public static final String STORE_TIME_ZONE = "storeTimeZone"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/000077500000000000000000000000001360667575700265115ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/connectionprovider/000077500000000000000000000000001360667575700324235ustar00rootroot00000000000000EncryptedPasswordC3P0ConnectionProvider.java000066400000000000000000000127361360667575700430210ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.connectionprovider; import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.connection.C3P0ConnectionProvider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link C3P0ConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordC3P0ConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="c3p0.min_size">5</property>
 *      <property name="c3p0.max_size">20</property>
 *      <property name="c3p0.timeout">1800</property>
 *      <property name="c3p0.max_statements">50</property>
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.connectionprovider since 1.4) * * @author Daniel Fernández * */ public final class EncryptedPasswordC3P0ConnectionProvider extends C3P0ConnectionProvider { public EncryptedPasswordC3P0ConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(Environment.DRIVER); final String url = props.getProperty(Environment.URL); final String user = props.getProperty(Environment.USER); final String password = props.getProperty(Environment.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( Environment.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( Environment.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( Environment.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( Environment.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate do the rest super.configure(props); } } EncryptedPasswordDriverManagerConnectionProvider.java000066400000000000000000000125531360667575700450770ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.connectionprovider; import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.connection.DriverManagerConnectionProvider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link DriverManagerConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      <!-- Database connection settings -->
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="connection.pool_size">5</property>
 *      
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.connectionprovider since 1.4) * * @author Daniel Fernández * */ public final class EncryptedPasswordDriverManagerConnectionProvider extends DriverManagerConnectionProvider { public EncryptedPasswordDriverManagerConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(Environment.DRIVER); final String url = props.getProperty(Environment.URL); final String user = props.getProperty(Environment.USER); final String password = props.getProperty(Environment.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( Environment.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( Environment.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( Environment.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( Environment.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate process super.configure(props); } } ParameterNaming.java000066400000000000000000000033001360667575700362550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.connectionprovider; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; /** *

* Constant names of the parameters that can be used by a jasypt's * Hibernate connection provider. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.connectionprovider since 1.4) * * @author Daniel Fernández * */ public final class ParameterNaming { /** * Property in hibernate.cfg.xml or * hibernate.properties which contains the registered name * (in {@link HibernatePBEEncryptorRegistry}) of the encryptor which * will be used to decrypt the datasource parameters. */ public static final String ENCRYPTOR_REGISTERED_NAME = "hibernate.connection.encryptor_registered_name"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/000077500000000000000000000000001360667575700305365ustar00rootroot00000000000000HibernatePBEBigDecimalEncryptor.java000066400000000000000000000334211360667575700373640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.encryptor; import java.math.BigDecimal; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigDecimalEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigDecimalEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigDecimalEncryptor be explicitly set * with {@link #setEncryptor(PBEBigDecimalEncryptor)}. If not, a * StandardPBEBigDecimalEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, * {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigDecimalEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigDecimalEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigDecimalEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigDecimalEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigDecimalEncryptor * objects this way to wrap PBEBigDecimalEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigDecimalEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.encryptor since 1.2) * * @author Daniel Fernández * */ public final class HibernatePBEBigDecimalEncryptor { private String registeredName = null; private PBEBigDecimalEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigDecimalEncryptor It also * creates a StandardPBEBigDecimalEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigDecimalEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigDecimalEncryptor * is registered programmatically. */ HibernatePBEBigDecimalEncryptor(final String registeredName, final PBEBigDecimalEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigDecimalEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigDecimalEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigDecimalEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the iv generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigDecimal encrypt(final BigDecimal message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigDecimal decrypt(final BigDecimal encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigDecimalEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigDecimalEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEBigIntegerEncryptor.java000066400000000000000000000333271360667575700374300ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.encryptor; import java.math.BigInteger; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigIntegerEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigIntegerEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigIntegerEncryptor be explicitly set * with {@link #setEncryptor(PBEBigIntegerEncryptor)}. If not, a * StandardPBEBigIntegerEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, * {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigIntegerEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigIntegerEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigIntegerEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigIntegerEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigIntegerEncryptor * objects this way to wrap PBEBigIntegerEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigIntegerEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.encryptor since 1.2) * * @author Daniel Fernández * */ public final class HibernatePBEBigIntegerEncryptor { private String registeredName = null; private PBEBigIntegerEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigIntegerEncryptor It also * creates a StandardPBEBigIntegerEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigIntegerEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigIntegerEncryptor * is registered programmatically. */ HibernatePBEBigIntegerEncryptor(final String registeredName, final PBEBigIntegerEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigIntegerEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigIntegerEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigIntegerEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigInteger encrypt(final BigInteger message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigInteger decrypt(final BigInteger encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigIntegerEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigIntegerEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEByteEncryptor.java000066400000000000000000000325101360667575700363050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.encryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEByteEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEByteEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEByteEncryptor be explicitly set * with {@link #setEncryptor(PBEByteEncryptor)}. If not, a * StandardPBEByteEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, * {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="byteEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEByteEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEByteEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateByteEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="byteEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEByteEncryptor * objects this way to wrap PBEByteEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEByteEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.encryptor since 1.2) * * @author Daniel Fernández * */ public final class HibernatePBEByteEncryptor { private String registeredName = null; private PBEByteEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEByteEncryptor It also * creates a StandardPBEByteEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEByteEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEByteEncryptor * is registered programmatically. */ HibernatePBEByteEncryptor(final String registeredName, final PBEByteEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEByteEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEByteEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEByteEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public byte[] encrypt(final byte[] message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public byte[] decrypt(final byte[] encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEByteEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEByteEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEEncryptorRegistry.java000066400000000000000000000265171360667575700372240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.encryptor; import java.util.HashMap; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Registry for all the PBE*Encryptor which are eligible for * use from Hibernate. *

*

* This class is intended to be directly used in applications where * an IoC container (like Spring Framework) is not present. If it is, * it is better to use the HibernatePBE*Encryptor classes * directly, instead. *

*

* This registry is a singleton which maintains a registry * of PBE*Encryptor objects which can be used from Hibernate, * by using its registeredName to reference them from mappings. *

*

* The steps would be: *

    *
  1. Obtain the registry instance ({@link #getInstance()}).
  2. *
  3. Register the encryptor, giving it a registered name * (registerPBE*Encryptor(String, PBE*Encryptor).
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * when registering the encryptor.
  6. *
*

*

* This is, first register the encryptor (example with a String encryptor): *

*

*

 *  StandardPBEStringEncryptor myEncryptor = new StandardPBEStringEncryptor();
 *  ...
 *  HibernatePBEEncryptorRegistry registry =
 *      HibernatePBEEncryptorRegistry.getInstance();
 *  registry.registerPBEStringEncryptor("myHibernateEncryptor", myEncryptor);
 * 
*

*

* And then, reference it from a Hibernate mapping file: *

*

*

 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateEncryptor</param>
 *    </typedef>
 * 
*

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.encryptor since 1.2) * * @author Daniel Fernández * */ public final class HibernatePBEEncryptorRegistry { // The singleton instance private static final HibernatePBEEncryptorRegistry instance = new HibernatePBEEncryptorRegistry(); // Registry maps private final HashMap stringEncryptors = new HashMap(); private final HashMap bigIntegerEncryptors = new HashMap(); private final HashMap bigDecimalEncryptors = new HashMap(); private final HashMap byteEncryptors = new HashMap(); /** * Returns the singleton instance of the registry. * * @return the registry. */ public static HibernatePBEEncryptorRegistry getInstance() { return instance; } // The registry cannot be externally instantiated. private HibernatePBEEncryptorRegistry() { super(); } /** * Registers a PBEStringEncryptor object with the specified * name. * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEStringEncryptor( final String registeredName, final PBEStringEncryptor encryptor) { final HibernatePBEStringEncryptor hibernateEncryptor = new HibernatePBEStringEncryptor(registeredName, encryptor); this.stringEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void registerHibernatePBEStringEncryptor( final HibernatePBEStringEncryptor hibernateEncryptor) { this.stringEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEStringEncryptor(final String name) { this.stringEncryptors.remove(name); } /** * Returns the PBEStringEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEStringEncryptor getPBEStringEncryptor( final String registeredName) { final HibernatePBEStringEncryptor hibernateEncryptor = (HibernatePBEStringEncryptor) this.stringEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigIntegerEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigIntegerEncryptor( final String registeredName, final PBEBigIntegerEncryptor encryptor) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = new HibernatePBEBigIntegerEncryptor(registeredName, encryptor); this.bigIntegerEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigIntegerEncryptor( final HibernatePBEBigIntegerEncryptor hibernateEncryptor) { this.bigIntegerEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigIntegerEncryptor(final String name) { this.bigIntegerEncryptors.remove(name); } /** * Returns the PBEBigIntegerEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigIntegerEncryptor getPBEBigIntegerEncryptor( final String registeredName) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = (HibernatePBEBigIntegerEncryptor) this.bigIntegerEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigDecimalEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigDecimalEncryptor( final String registeredName, final PBEBigDecimalEncryptor encryptor) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = new HibernatePBEBigDecimalEncryptor(registeredName, encryptor); this.bigDecimalEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigDecimalEncryptor( final HibernatePBEBigDecimalEncryptor hibernateEncryptor) { this.bigDecimalEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigDecimalEncryptor(final String name) { this.bigDecimalEncryptors.remove(name); } /** * Returns the PBEBigDecimalEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigDecimalEncryptor getPBEBigDecimalEncryptor( final String registeredName) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = (HibernatePBEBigDecimalEncryptor) this.bigDecimalEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEByteEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEByteEncryptor( final String registeredName, final PBEByteEncryptor encryptor) { final HibernatePBEByteEncryptor hibernateEncryptor = new HibernatePBEByteEncryptor(registeredName, encryptor); this.byteEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void registerHibernatePBEByteEncryptor( final HibernatePBEByteEncryptor hibernateEncryptor) { this.byteEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEByteEncryptor(final String name) { this.byteEncryptors.remove(name); } /** * Returns the PBEByteEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEByteEncryptor getPBEByteEncryptor( final String registeredName) { final HibernatePBEByteEncryptor hibernateEncryptor = (HibernatePBEByteEncryptor) this.byteEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } } HibernatePBEStringEncryptor.java000066400000000000000000000376421360667575700366630ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.encryptor; import java.security.Provider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEStringEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEStringEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEStringEncryptor be explicitly set * with {@link #setEncryptor(PBEStringEncryptor)}. If not, a * StandardPBEStringEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)}, * {@link #setProviderName(String)}, * {@link #setProvider(Provider)}, {@link #setStringOutputType(String)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="stringEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateStringEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="stringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEStringEncryptor * objects this way to wrap PBEStringEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEStringEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.encryptor since 1.2) * * @author Daniel Fernández * */ public final class HibernatePBEStringEncryptor { private String registeredName = null; private PBEStringEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEStringEncryptor. It also * creates a StandardPBEStringEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEStringEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEStringEncryptor * is registered programmatically. */ HibernatePBEStringEncryptor(final String registeredName, final PBEStringEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public synchronized PBEStringEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEStringEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public synchronized void setEncryptor(final PBEStringEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setIvGenerator(ivGenerator); } /** * Sets the name of the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param providerName the name of the JCE provider (already registered) */ public void setProviderName(final String providerName) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProviderName(providerName); } /** * Sets the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param provider the JCE provider to be used */ public void setProvider(final Provider provider) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProvider(provider); } /** * Sets the type of String output ("base64" (default), "hexadecimal") to * be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param stringOutputType the type of String output */ public void setStringOutputType(final String stringOutputType) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setStringOutputType(stringOutputType); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public String encrypt(final String message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public String decrypt(final String encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEStringEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEStringEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/000077500000000000000000000000001360667575700274725ustar00rootroot00000000000000AbstractEncryptedAsStringType.java000066400000000000000000000233211360667575700362150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; /** * * Base class for Hibernate UserTypes to store * values as encrypted strings. * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * @author Daniel Fernández * @author Iván García Sáinz-Aja * */ public abstract class AbstractEncryptedAsStringType implements UserType, ParameterizedType { static final int sqlType = Types.VARCHAR; static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String providerName = null; private String password = null; private Integer keyObtentionIterations = null; private String stringOutputType = null; protected PBEStringEncryptor encryptor = null; /** * Converts given String to its Object form. * @param string the string value * @return the object form of the passed String */ protected abstract Object convertToObject(final String string); /** * Converts given Object to its String form. * @param object the object value * @return the string form of the passes Object */ protected String convertToString(final Object object) { return object == null? null : object.toString(); } public final int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public abstract Class returnedClass(); public final boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public final Object deepCopy(final Object value) throws HibernateException { return value; } public final Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public final Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public final boolean isMutable() { return false; } public final int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public final Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public final Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final String message = rs.getString(names[0]); return rs.wasNull() ? null : convertToObject(this.encryptor.decrypt(message)); } public final void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { st.setString(index, this.encryptor.encrypt(convertToString(value))); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramProviderName = parameters.getProperty(ParameterNaming.PROVIDER_NAME); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramStringOutputType = parameters.getProperty(ParameterNaming.STRING_OUTPUT_TYPE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramProviderName != null) { this.providerName = paramProviderName; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } if (paramStringOutputType != null) { this.stringOutputType = paramStringOutputType; } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } protected synchronized final void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor pbeEncryptor = registry.getPBEStringEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEStringEncryptor newEncryptor = new StandardPBEStringEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.providerName != null) { newEncryptor.setProviderName(this.providerName); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } if (this.stringOutputType != null) { newEncryptor.setStringOutputType(this.stringOutputType); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigDecimalAsStringType.java000066400000000000000000000076731360667575700364460ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.math.BigDecimal; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigDecimal values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBigDecimalAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigDecimal(string); } public Class returnedClass() { return BigDecimal.class; } } EncryptedBigDecimalType.java000066400000000000000000000321211360667575700347550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.io.Serializable; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEBigDecimalEncryptor; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigDecimal values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigDecimalEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigDecimalEncryptor (see * {@link HibernatePBEBigDecimalEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

*

* About the decimalScale parameter *

* The decimalScale parameter is aimed at setting the scale with which * BigDecimal numbers will be set to and retrieved from the database. It is * an important parameter because many DBMSs return BigDecimal numbers with * a scale equal to the amount of decimal positions declared for the field * (e.g. if we store "18.23" (scale=2) in a DECIMAL(15,5) field, we can get a * "18.23000" (scale=5) back when we retrieve the number). This can affect * correct decryption of encrypted numbers, but specifying a * decimalScale parameter will solve this issue. *

*

* So, if we set decimalScale to 3, and we store "18.23", this * Hibernate type will send "18.230" to the encryptor, which is the value that * we will get back from the database at retrieval time (a scale of "3" * will be set again on the value obtained from DB). If it is necessary, a * DOWN rounding operation is executed on the number. *

*
*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBigDecimalType implements UserType, ParameterizedType { private static final int sqlType = Types.NUMERIC; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private Integer decimalScale = null; private PBEBigDecimalEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigDecimal.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal storedEncryptedMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigDecimal scaledEncryptedMessage = storedEncryptedMessage.setScale( this.decimalScale.intValue(), BigDecimal.ROUND_UNNECESSARY); return this.encryptor.decrypt(scaledEncryptedMessage); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigDecimal scaledValue = ((BigDecimal) value).setScale( this.decimalScale.intValue(), BigDecimal.ROUND_DOWN); final BigDecimal encryptedMessage = this.encryptor.encrypt(scaledValue); st.setBigDecimal(index, encryptedMessage); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramDecimalScale = parameters.getProperty(ParameterNaming.DECIMAL_SCALE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } if (paramDecimalScale != null) { try { this.decimalScale = new Integer(Integer.parseInt(paramDecimalScale)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.DECIMAL_SCALE + "\" is not a valid integer"); } } else { throw new EncryptionInitializationException( ParameterNaming.DECIMAL_SCALE + " must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigDecimalEncryptor pbeEncryptor = registry.getPBEBigDecimalEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big decimal encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigDecimalEncryptor newEncryptor = new StandardPBEBigDecimalEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigIntegerAsStringType.java000066400000000000000000000076731360667575700365050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.math.BigInteger; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigInteger values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBigIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigInteger(string); } public Class returnedClass() { return BigInteger.class; } } EncryptedBigIntegerType.java000066400000000000000000000256431360667575700350270ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEBigIntegerEncryptor; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigInteger values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigIntegerEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigIntegerEncryptor (see * {@link HibernatePBEBigIntegerEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBigIntegerType implements UserType, ParameterizedType { private static int sqlType = Types.NUMERIC; private static int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEBigIntegerEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigInteger.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return EqualsHelper.equals(x, y); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal decimalMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigInteger message = decimalMessage.setScale(0, BigDecimal.ROUND_UNNECESSARY). unscaledValue(); return this.encryptor.decrypt(message); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigInteger encryptedMessage = this.encryptor.encrypt((BigInteger) value); st.setBigDecimal(index, new BigDecimal(encryptedMessage)); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigIntegerEncryptor pbeEncryptor = registry.getPBEBigIntegerEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigIntegerEncryptor newEncryptor = new StandardPBEBigIntegerEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBinaryType.java000066400000000000000000000320061360667575700342230ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.cfg.Environment; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate3.encryptor.HibernatePBEByteEncryptor; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of byte[] values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEByteEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateByteEncryptor (see * {@link HibernatePBEByteEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBinaryType implements UserType, ParameterizedType { private static final int BLOCK_SIZE = 2048; private static final int sqlType = Types.VARBINARY; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEByteEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return byte[].class; } public boolean equals(final Object x, final Object y) throws HibernateException { return (x == y) || (x != null && y != null && java.util.Arrays.equals((byte[]) x, (byte[]) y)); } public Object deepCopy(final Object value) throws HibernateException { if (value == null) { return null; } final byte[] valueBytes = (byte[]) value; final byte[] copyBytes = new byte[valueBytes.length]; System.arraycopy(valueBytes, 0, copyBytes, 0, valueBytes.length); return copyBytes; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return true; } public int hashCode(final Object x) throws HibernateException { final byte[] valueBytes = (byte[]) x; int result = 1; for (int i = 0; i < valueBytes.length; i++ ) { result = (result * 17) + valueBytes[i]; } return result; } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return (original == null)? null : deepCopy(original); } public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException { checkInitialization(); byte[] encryptedValue = null; if (Environment.useStreamsForBinary()) { final InputStream inputStream = rs.getBinaryStream(names[0]); if (rs.wasNull()) { return null; } final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BLOCK_SIZE); final byte[] inputBuff = new byte[BLOCK_SIZE]; try { int readBytes = 0; while (readBytes != -1) { readBytes = inputStream.read(inputBuff); if (readBytes != -1) { outputStream.write(inputBuff, 0, readBytes); } } } catch (IOException e) { throw new HibernateException( "IOException occurred reading a binary value", e); } finally { try { inputStream.close(); } catch (IOException e) { // exception ignored } try { outputStream.close(); } catch (IOException e) { // exception ignored } } encryptedValue = outputStream.toByteArray(); } else { encryptedValue = rs.getBytes(names[0]); if (rs.wasNull()) { return null; } } return this.encryptor.decrypt(encryptedValue); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final byte[] encryptedValue = this.encryptor.encrypt((byte[]) value); if (Environment.useStreamsForBinary()) { st.setBinaryStream( index, new ByteArrayInputStream(encryptedValue), encryptedValue.length); } else { st.setBytes(index, encryptedValue); } } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEByteEncryptor pbeEncryptor = registry.getPBEByteEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEByteEncryptor newEncryptor = new StandardPBEByteEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBooleanAsStringType.java000066400000000000000000000076071360667575700360420ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Boolean values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedBooleanAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return Boolean.valueOf(string); } public Class returnedClass() { return Boolean.class; } } EncryptedByteAsStringType.java000066400000000000000000000075461360667575700353700ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Byte values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedByteAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Byte(string); } public Class returnedClass() { return Byte.class; } } EncryptedCalendarAsStringType.java000066400000000000000000000135351360667575700361710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.util.Calendar; import java.util.Properties; import java.util.TimeZone; import org.jasypt.commons.CommonUtils; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Calendar values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* The boolean storeTimeZone parameter allows the Calendar to be * re-created with the same TimeZone that it was created. This is an * optional parameter, and its default value is FALSE. *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedCalendarAsStringType extends AbstractEncryptedAsStringType{ private Boolean storeTimeZone = Boolean.FALSE; /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final String[] stringTokens = CommonUtils.split(string); TimeZone tz = null; final long timeMillis = Long.valueOf(stringTokens[0]).longValue(); if (this.storeTimeZone.booleanValue()) { tz = TimeZone.getTimeZone(stringTokens[1]); } else { tz = TimeZone.getDefault(); } final Calendar cal = Calendar.getInstance(); cal.setTimeZone(tz); cal.setTimeInMillis(timeMillis); return cal; } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final StringBuffer strBuff = new StringBuffer(); final long timeMillis = ((Calendar) object).getTimeInMillis(); strBuff.append((new Long(timeMillis)).toString()); if (this.storeTimeZone.booleanValue()) { strBuff.append(" "); strBuff.append(((Calendar) object).getTimeZone().getID()); } return strBuff.toString(); } public synchronized void setParameterValues(final Properties parameters) { super.setParameterValues(parameters); final String paramStoreTimeZone = parameters.getProperty(ParameterNaming.STORE_TIME_ZONE); if ((paramStoreTimeZone != null) && (!paramStoreTimeZone.trim().equals(""))) { this.storeTimeZone = CommonUtils.getStandardBooleanValue(paramStoreTimeZone); } } public Class returnedClass() { return Calendar.class; } } EncryptedDateAsStringType.java000066400000000000000000000103401360667575700353240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import java.util.Date; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Date values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedDateAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final long timeMillis = Long.valueOf(string).longValue(); return new Date(timeMillis); } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final long timeMillis = ((Date) object).getTime(); return String.valueOf(timeMillis); } public Class returnedClass() { return Date.class; } } EncryptedDoubleAsStringType.java000066400000000000000000000075721360667575700356760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Double values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedDoubleAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Double(string); } public Class returnedClass() { return Double.class; } } EncryptedFloatAsStringType.java000066400000000000000000000075611360667575700355270ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Float values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedFloatAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Float(string); } public Class returnedClass() { return Float.class; } } EncryptedIntegerAsStringType.java000066400000000000000000000076071360667575700360600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Integer values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Integer(string); } public Class returnedClass() { return Integer.class; } } EncryptedLongAsStringType.java000066400000000000000000000075511360667575700353600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Long values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedLongAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Long(string); } public Class returnedClass() { return Long.class; } } EncryptedShortAsStringType.java000066400000000000000000000075701360667575700355610ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Short values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedShortAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Short(string); } public Class returnedClass() { return Short.class; } } EncryptedStringType.java000066400000000000000000000074601360667575700342530ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows transparent * encryption of String values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.2) * * @author Daniel Fernández * */ public final class EncryptedStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String stringValue) { return stringValue; } public Class returnedClass() { return String.class; } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/main/java/org/jasypt/hibernate3/type/ParameterNaming.java000066400000000000000000000064431360667575700334160ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.type; /** *

* Constant names of the parameters that can be used by a jasypt type's * typedef declaration in a Hibernate mapping. *

* * @since 1.9.0 (class existed in package * org.jasypt.hibernate.type since 1.4) * * @author Daniel Fernández * */ public final class ParameterNaming { /** *

* The registered name of an encryptor previously registered at the * {@link org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry}. *

*

* Value = encryptorRegisteredName *

*/ public static final String ENCRYPTOR_NAME = "encryptorRegisteredName"; /** *

* The encryption algorithm. *

*

* Value = algorithm *

*/ public static final String ALGORITHM = "algorithm"; /** *

* The name of the JCE security provider we want to get the algorithm from * (if it is no the default one. *

*

* Value = providerName *

*/ public static final String PROVIDER_NAME = "providerName"; /** *

* The encryption password. *

*

* Value = password *

*/ public static final String PASSWORD = "password"; /** *

* The number of hashing iterations to be applied for obtaining the * encryption key. *

*

* Value = keyObtentionIterations *

*/ public static final String KEY_OBTENTION_ITERATIONS = "keyObtentionIterations"; /** *

* The type of String output ("base64" (default), "hexadecimal") to be * generated. *

*

* Value = stringOutputType *

*/ public static final String STRING_OUTPUT_TYPE = "stringOutputType"; /** *

* The scale (numbers after the decimal point) to be used when storing * decimal numbers. *

*

* Value = decimalScale *

*/ public static final String DECIMAL_SCALE = "decimalScale"; /** *

* Whether the calendar time zone should be stored with the date or not. *

*

* Value = storeTimeZone *

*/ public static final String STORE_TIME_ZONE = "storeTimeZone"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/000077500000000000000000000000001360667575700214765ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/000077500000000000000000000000001360667575700224175ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/000077500000000000000000000000001360667575700232065ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/000077500000000000000000000000001360667575700245205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/000077500000000000000000000000001360667575700265445ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/model/000077500000000000000000000000001360667575700276445ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/model/user/000077500000000000000000000000001360667575700306225ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/model/user/User.hbm.xml000066400000000000000000000027471360667575700330410ustar00rootroot00000000000000 hibernateStringEncryptor hibernateStringEncryptor hibernateByteEncryptor jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/model/user/User.java000066400000000000000000000045501360667575700324070ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.model.user; import java.util.Calendar; import org.apache.commons.lang.builder.ToStringBuilder; /** * * @author Soraya Sánchez * */ public class User { private String name; private String login; private String password; private Calendar birthdate; private byte[] document; public User(String name, String login, String password, Calendar birthdate, byte[] document) { super(); this.name = name; this.login = login; this.password = password; this.birthdate = birthdate; this.document = document; } public User() { super(); } public String toString() { return new ToStringBuilder(this).append("name", this.name) .append("login", this.login).append("password", this.password) .append("birthdate", this.birthdate) .append("document", this.document).toString(); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getLogin() { return this.login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Calendar getBirthdate() { return this.birthdate; } public void setBirthdate(Calendar birthdate) { this.birthdate = birthdate; } public byte[] getDocument() { return this.document; } public void setDocument(byte[] document) { this.document = document; } } jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/test/000077500000000000000000000000001360667575700275235ustar00rootroot00000000000000TestHibernateTypes.java000066400000000000000000000134501360667575700341000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate3/src/test/java/org/jasypt/hibernate3/test/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate3.test; import java.io.UnsupportedEncodingException; import java.sql.SQLException; import java.util.Calendar; import junit.framework.TestCase; import org.apache.commons.lang.RandomStringUtils; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate3.model.user.User; /** * * @author Soraya Sánchez * */ public class TestHibernateTypes extends TestCase { private static Configuration hbConf; private static SessionFactory sessionFactory; private static String userLogin; private static String userName; private static String userPassword; private static Calendar userBirthdate; private static byte[] userDocument; static Session session; public TestHibernateTypes() { super(); } public TestHibernateTypes(String name) { super(name); } public void testCreateAndReadUser() throws Exception { initialize(); createUser(); readUser(); finish(); } private void initialize() { registerEncryptors(); // Configure Hibernate and open session hbConf = new Configuration(); hbConf .addClass(User.class) .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect") .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:jasypttestdb") .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver") .setProperty("hibernate.connection.username", "sa") .setProperty("hibernate.connection.password", "") .setProperty("hibernate.connection.pool_size", "10"); sessionFactory = hbConf.buildSessionFactory(); session = sessionFactory.openSession(); initDB(); generateData(); } private void registerEncryptors() { StandardPBEStringEncryptor stringEncryptor = new StandardPBEStringEncryptor(); stringEncryptor.setAlgorithm("PBEWithMD5AndDES"); stringEncryptor.setPassword("jasypt-hibernate3-test"); StandardPBEByteEncryptor byteEncryptor = new StandardPBEByteEncryptor(); byteEncryptor.setAlgorithm("PBEWithMD5AndDES"); byteEncryptor.setPassword("jasypt-hibernate3-test"); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("hibernateStringEncryptor", stringEncryptor); registry.registerPBEByteEncryptor("hibernateByteEncryptor", byteEncryptor); } /** * Create db structure */ private void initDB() { Transaction transaction = session.beginTransaction(); try { session.connection().createStatement() .execute( "CREATE MEMORY TABLE PUBLIC.USER(" + "NAME VARCHAR(100)," + "LOGIN VARCHAR(100) PRIMARY KEY," + "PASSWORD VARCHAR(100)," + "BIRTHDATE VARCHAR(100)," + "DOCUMENT BLOB);"); } catch (HibernateException e) { e.printStackTrace(); assertTrue(false); } catch (SQLException e) { e.printStackTrace(); assertTrue(false); } transaction.commit(); } /** * Generate data to test with */ private void generateData() { userLogin = RandomStringUtils.randomAlphabetic(5); userName = RandomStringUtils.randomAlphabetic(10); userPassword = RandomStringUtils.randomAlphanumeric(15); userBirthdate = Calendar.getInstance(); try { userDocument = RandomStringUtils.randomAlphabetic(100).getBytes( "ISO-8859-1"); } catch (UnsupportedEncodingException e) { assertTrue(false); } } private void finish() { session.close(); } private void createUser() throws Exception { User user = new User(userName, userLogin, userPassword, userBirthdate, userDocument); Transaction transaction = session.beginTransaction(); session.saveOrUpdate(user); System.out.println("User stored: " + user); transaction.commit(); assertTrue(true); } private void readUser() throws Exception { Transaction transaction = session.beginTransaction(); User user = (User) session.load(User.class, userLogin); System.out.println("User read: " + user); transaction.commit(); assertEquals(user.getLogin(), userLogin); assertEquals(user.getName(), userName); assertEquals(user.getPassword(), userPassword); assertEquals(user.getBirthdate(), userBirthdate); assertEquals(user.getDocument(), userDocument); } } jasypt-jasypt-1.9.3/jasypt-hibernate4/000077500000000000000000000000001360667575700177315ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/.gitignore000066400000000000000000000000721360667575700217200ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-hibernate4/BUILD.txt000066400000000000000000000015111360667575700213270ustar00rootroot00000000000000 Building JASYPT-HIBERNATE4 -------------------------- To build JASYPT-HIBERNATE4 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-HIBERNATE4 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-hibernate4-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-hibernate4/{version}/jasypt-hibernate4-{version}.jar Generating Javadoc for JASYPT-HIBERNATE4 ---------------------------------------- If you wish to generate the javadoc for JASYPT-HIBERNATE4, execute this from the JASYPT-HIBERNATE4 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-hibernate4/ChangeLog.txt000066400000000000000000000005461360667575700223260ustar00rootroot000000000000001.9.3 ===== - Fixed #32: encryption works but decryption does not, Java 8 (JCE jars installed). Added support for initialization vectors needed for AES encryption and decryption since Java 8. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Created new jasypt-hibernate4 module for Hibernate 4 integration. - Created additional tests jasypt-jasypt-1.9.3/jasypt-hibernate4/LICENSE.txt000066400000000000000000000261361360667575700215640ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-hibernate4/NOTICE.txt000066400000000000000000000072671360667575700214670ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-hibernate4/README.txt000066400000000000000000000006111360667575700214250ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-hibernate4/RELEASING.txt000066400000000000000000000023061360667575700220040ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-hibernate4/USAGE.txt000066400000000000000000000012041360667575700213330ustar00rootroot00000000000000 Using JASYPT-HIBERNATE4 from Maven 2 ------------------------------------ In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-hibernate4 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-hibernate4/pom.xml000066400000000000000000000177071360667575700212620ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-hibernate4 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true jboss-nexus-repository JBoss Nexus Repository http://repository.jboss.org/nexus/content/groups/public-jboss/ src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/java ** **/*.java src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.1 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.hibernate hibernate-core 4.0.0.CR7 provided true org.hibernate hibernate-c3p0 4.0.0.CR7 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test org.hsqldb hsqldb 2.2.6 test jasypt-jasypt-1.9.3/jasypt-hibernate4/src/000077500000000000000000000000001360667575700205205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/000077500000000000000000000000001360667575700214445ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/000077500000000000000000000000001360667575700223655ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/000077500000000000000000000000001360667575700231545ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/000077500000000000000000000000001360667575700244665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/000077500000000000000000000000001360667575700265135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/connectionprovider/000077500000000000000000000000001360667575700324255ustar00rootroot00000000000000EncryptedPasswordC3P0ConnectionProvider.java000066400000000000000000000130241360667575700430120ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.connectionprovider; import java.util.Properties; import org.hibernate.cfg.AvailableSettings; import org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link C3P0ConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordC3P0ConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="c3p0.min_size">5</property>
 *      <property name="c3p0.max_size">20</property>
 *      <property name="c3p0.timeout">1800</property>
 *      <property name="c3p0.max_statements">50</property>
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedPasswordC3P0ConnectionProvider extends C3P0ConnectionProvider { private static final long serialVersionUID = 5273353009914873806L; public EncryptedPasswordC3P0ConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(AvailableSettings.DRIVER); final String url = props.getProperty(AvailableSettings.URL); final String user = props.getProperty(AvailableSettings.USER); final String password = props.getProperty(AvailableSettings.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( AvailableSettings.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( AvailableSettings.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( AvailableSettings.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( AvailableSettings.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate do the rest super.configure(props); } } EncryptedPasswordDriverManagerConnectionProvider.java000066400000000000000000000126551360667575700451040ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.connectionprovider; import java.util.Properties; import org.hibernate.cfg.AvailableSettings; import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link DriverManagerConnectionProviderImpl} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      <!-- Database connection settings -->
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="connection.pool_size">5</property>
 *      
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedPasswordDriverManagerConnectionProvider extends DriverManagerConnectionProviderImpl { private static final long serialVersionUID = 7409509667904250297L; public EncryptedPasswordDriverManagerConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(AvailableSettings.DRIVER); final String url = props.getProperty(AvailableSettings.URL); final String user = props.getProperty(AvailableSettings.USER); final String password = props.getProperty(AvailableSettings.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( AvailableSettings.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( AvailableSettings.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( AvailableSettings.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( AvailableSettings.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate process super.configure(props); } } ParameterNaming.java000066400000000000000000000031451360667575700362660ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.connectionprovider; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; /** *

* Constant names of the parameters that can be used by a jasypt's * Hibernate connection provider. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class ParameterNaming { /** * Property in hibernate.cfg.xml or * hibernate.properties which contains the registered name * (in {@link HibernatePBEEncryptorRegistry}) of the encryptor which * will be used to decrypt the datasource parameters. */ public static final String ENCRYPTOR_REGISTERED_NAME = "hibernate.connection.encryptor_registered_name"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/000077500000000000000000000000001360667575700305405ustar00rootroot00000000000000HibernatePBEBigDecimalEncryptor.java000066400000000000000000000332721360667575700373720ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.encryptor; import java.math.BigDecimal; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigDecimalEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigDecimalEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigDecimalEncryptor be explicitly set * with {@link #setEncryptor(PBEBigDecimalEncryptor)}. If not, a * StandardPBEBigDecimalEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigDecimalEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigDecimalEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigDecimalEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigDecimalEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigDecimalEncryptor * objects this way to wrap PBEBigDecimalEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigDecimalEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class HibernatePBEBigDecimalEncryptor { private String registeredName = null; private PBEBigDecimalEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigDecimalEncryptor It also * creates a StandardPBEBigDecimalEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigDecimalEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigDecimalEncryptor * is registered programmatically. */ HibernatePBEBigDecimalEncryptor(final String registeredName, final PBEBigDecimalEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigDecimalEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigDecimalEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigDecimalEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the iv generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigDecimal encrypt(final BigDecimal message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigDecimal decrypt(final BigDecimal encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigDecimalEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigDecimalEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEBigIntegerEncryptor.java000066400000000000000000000332021360667575700374220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.encryptor; import java.math.BigInteger; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigIntegerEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigIntegerEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigIntegerEncryptor be explicitly set * with {@link #setEncryptor(PBEBigIntegerEncryptor)}. If not, a * StandardPBEBigIntegerEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigIntegerEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigIntegerEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigIntegerEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigIntegerEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigIntegerEncryptor * objects this way to wrap PBEBigIntegerEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigIntegerEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class HibernatePBEBigIntegerEncryptor { private String registeredName = null; private PBEBigIntegerEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigIntegerEncryptor It also * creates a StandardPBEBigIntegerEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigIntegerEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigIntegerEncryptor * is registered programmatically. */ HibernatePBEBigIntegerEncryptor(final String registeredName, final PBEBigIntegerEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigIntegerEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigIntegerEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigIntegerEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigInteger encrypt(final BigInteger message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigInteger decrypt(final BigInteger encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigIntegerEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigIntegerEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEByteEncryptor.java000066400000000000000000000323631360667575700363150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.encryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEByteEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEByteEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEByteEncryptor be explicitly set * with {@link #setEncryptor(PBEByteEncryptor)}. If not, a * StandardPBEByteEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="byteEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEByteEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEByteEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateByteEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="byteEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEByteEncryptor * objects this way to wrap PBEByteEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEByteEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class HibernatePBEByteEncryptor { private String registeredName = null; private PBEByteEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEByteEncryptor It also * creates a StandardPBEByteEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEByteEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEByteEncryptor * is registered programmatically. */ HibernatePBEByteEncryptor(final String registeredName, final PBEByteEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEByteEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEByteEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEByteEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public byte[] encrypt(final byte[] message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public byte[] decrypt(final byte[] encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEByteEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEByteEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEEncryptorRegistry.java000066400000000000000000000263751360667575700372300ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.encryptor; import java.util.HashMap; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Registry for all the PBE*Encryptor which are eligible for * use from Hibernate. *

*

* This class is intended to be directly used in applications where * an IoC container (like Spring Framework) is not present. If it is, * it is better to use the HibernatePBE*Encryptor classes * directly, instead. *

*

* This registry is a singleton which maintains a registry * of PBE*Encryptor objects which can be used from Hibernate, * by using its registeredName to reference them from mappings. *

*

* The steps would be: *

    *
  1. Obtain the registry instance ({@link #getInstance()}).
  2. *
  3. Register the encryptor, giving it a registered name * (registerPBE*Encryptor(String, PBE*Encryptor).
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * when registering the encryptor.
  6. *
*

*

* This is, first register the encryptor (example with a String encryptor): *

*

*

 *  StandardPBEStringEncryptor myEncryptor = new StandardPBEStringEncryptor();
 *  ...
 *  HibernatePBEEncryptorRegistry registry =
 *      HibernatePBEEncryptorRegistry.getInstance();
 *  registry.registerPBEStringEncryptor("myHibernateEncryptor", myEncryptor);
 * 
*

*

* And then, reference it from a Hibernate mapping file: *

*

*

 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateEncryptor</param>
 *    </typedef>
 * 
*

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class HibernatePBEEncryptorRegistry { // The singleton instance private static final HibernatePBEEncryptorRegistry instance = new HibernatePBEEncryptorRegistry(); // Registry maps private final HashMap stringEncryptors = new HashMap(); private final HashMap bigIntegerEncryptors = new HashMap(); private final HashMap bigDecimalEncryptors = new HashMap(); private final HashMap byteEncryptors = new HashMap(); /** * Returns the singleton instance of the registry. * * @return the registry. */ public static HibernatePBEEncryptorRegistry getInstance() { return instance; } // The registry cannot be externally instantiated. private HibernatePBEEncryptorRegistry() { super(); } /** * Registers a PBEStringEncryptor object with the specified * name. * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEStringEncryptor( final String registeredName, final PBEStringEncryptor encryptor) { final HibernatePBEStringEncryptor hibernateEncryptor = new HibernatePBEStringEncryptor(registeredName, encryptor); this.stringEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void registerHibernatePBEStringEncryptor( final HibernatePBEStringEncryptor hibernateEncryptor) { this.stringEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEStringEncryptor(final String name) { this.stringEncryptors.remove(name); } /** * Returns the PBEStringEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEStringEncryptor getPBEStringEncryptor( final String registeredName) { final HibernatePBEStringEncryptor hibernateEncryptor = (HibernatePBEStringEncryptor) this.stringEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigIntegerEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigIntegerEncryptor( final String registeredName, final PBEBigIntegerEncryptor encryptor) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = new HibernatePBEBigIntegerEncryptor(registeredName, encryptor); this.bigIntegerEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigIntegerEncryptor( final HibernatePBEBigIntegerEncryptor hibernateEncryptor) { this.bigIntegerEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigIntegerEncryptor(final String name) { this.bigIntegerEncryptors.remove(name); } /** * Returns the PBEBigIntegerEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigIntegerEncryptor getPBEBigIntegerEncryptor( final String registeredName) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = (HibernatePBEBigIntegerEncryptor) this.bigIntegerEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigDecimalEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigDecimalEncryptor( final String registeredName, final PBEBigDecimalEncryptor encryptor) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = new HibernatePBEBigDecimalEncryptor(registeredName, encryptor); this.bigDecimalEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigDecimalEncryptor( final HibernatePBEBigDecimalEncryptor hibernateEncryptor) { this.bigDecimalEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigDecimalEncryptor(final String name) { this.bigDecimalEncryptors.remove(name); } /** * Returns the PBEBigDecimalEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigDecimalEncryptor getPBEBigDecimalEncryptor( final String registeredName) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = (HibernatePBEBigDecimalEncryptor) this.bigDecimalEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEByteEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEByteEncryptor( final String registeredName, final PBEByteEncryptor encryptor) { final HibernatePBEByteEncryptor hibernateEncryptor = new HibernatePBEByteEncryptor(registeredName, encryptor); this.byteEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void registerHibernatePBEByteEncryptor( final HibernatePBEByteEncryptor hibernateEncryptor) { this.byteEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEByteEncryptor(final String name) { this.byteEncryptors.remove(name); } /** * Returns the PBEByteEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEByteEncryptor getPBEByteEncryptor( final String registeredName) { final HibernatePBEByteEncryptor hibernateEncryptor = (HibernatePBEByteEncryptor) this.byteEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } } HibernatePBEStringEncryptor.java000066400000000000000000000375201360667575700366600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.encryptor; import java.security.Provider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEStringEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEStringEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEStringEncryptor be explicitly set * with {@link #setEncryptor(PBEStringEncryptor)}. If not, a * StandardPBEStringEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)}, * {@link #setProviderName(String)}, * {@link #setProvider(Provider)}, {@link #setStringOutputType(String)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="stringEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateStringEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="stringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEStringEncryptor * objects this way to wrap PBEStringEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEStringEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class HibernatePBEStringEncryptor { private String registeredName = null; private PBEStringEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEStringEncryptor. It also * creates a StandardPBEStringEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEStringEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEStringEncryptor * is registered programmatically. */ HibernatePBEStringEncryptor(final String registeredName, final PBEStringEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public synchronized PBEStringEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEStringEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public synchronized void setEncryptor(final PBEStringEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setIvGenerator(ivGenerator); } /** * Sets the name of the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param providerName the name of the JCE provider (already registered) */ public void setProviderName(final String providerName) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProviderName(providerName); } /** * Sets the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param provider the JCE provider to be used */ public void setProvider(final Provider provider) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProvider(provider); } /** * Sets the type of String output ("base64" (default), "hexadecimal") to * be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param stringOutputType the type of String output */ public void setStringOutputType(final String stringOutputType) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setStringOutputType(stringOutputType); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public String encrypt(final String message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public String decrypt(final String encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEStringEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEStringEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/000077500000000000000000000000001360667575700274745ustar00rootroot00000000000000AbstractEncryptedAsStringType.java000066400000000000000000000234141360667575700362220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; /** * * Base class for Hibernate UserTypes to store * values as encrypted strings. * * @since 1.9.0 * @author Daniel Fernández * @author Iván García Sáinz-Aja * */ public abstract class AbstractEncryptedAsStringType implements UserType, ParameterizedType { static final int sqlType = Types.VARCHAR; static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String providerName = null; private String password = null; private Integer keyObtentionIterations = null; private String stringOutputType = null; protected PBEStringEncryptor encryptor = null; /** * Converts given String to its Object form. * @param string the string value * @return the object form of the passed String */ protected abstract Object convertToObject(final String string); /** * Converts given Object to its String form. * @param object the object value * @return the string form of the passes Object */ protected String convertToString(final Object object) { return object == null? null : object.toString(); } public final int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public abstract Class returnedClass(); public final boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public final Object deepCopy(final Object value) throws HibernateException { return value; } public final Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public final Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public final boolean isMutable() { return false; } public final int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public final Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final String message = rs.getString(names[0]); return rs.wasNull() ? null : convertToObject(this.encryptor.decrypt(message)); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SessionImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { st.setString(index, this.encryptor.encrypt(convertToString(value))); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramProviderName = parameters.getProperty(ParameterNaming.PROVIDER_NAME); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramStringOutputType = parameters.getProperty(ParameterNaming.STRING_OUTPUT_TYPE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramProviderName != null) { this.providerName = paramProviderName; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } if (paramStringOutputType != null) { this.stringOutputType = paramStringOutputType; } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } protected synchronized final void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor pbeEncryptor = registry.getPBEStringEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEStringEncryptor newEncryptor = new StandardPBEStringEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.providerName != null) { newEncryptor.setProviderName(this.providerName); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } if (this.stringOutputType != null) { newEncryptor.setStringOutputType(this.stringOutputType); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigDecimalAsStringType.java000066400000000000000000000075561360667575700364500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.math.BigDecimal; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigDecimal values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBigDecimalAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigDecimal(string); } public Class returnedClass() { return BigDecimal.class; } } EncryptedBigDecimalType.java000066400000000000000000000322101360667575700347560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.io.Serializable; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEBigDecimalEncryptor; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigDecimal values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigDecimalEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigDecimalEncryptor (see * {@link HibernatePBEBigDecimalEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

*

* About the decimalScale parameter *

* The decimalScale parameter is aimed at setting the scale with which * BigDecimal numbers will be set to and retrieved from the database. It is * an important parameter because many DBMSs return BigDecimal numbers with * a scale equal to the amount of decimal positions declared for the field * (e.g. if we store "18.23" (scale=2) in a DECIMAL(15,5) field, we can get a * "18.23000" (scale=5) back when we retrieve the number). This can affect * correct decryption of encrypted numbers, but specifying a * decimalScale parameter will solve this issue. *

*

* So, if we set decimalScale to 3, and we store "18.23", this * Hibernate type will send "18.230" to the encryptor, which is the value that * we will get back from the database at retrieval time (a scale of "3" * will be set again on the value obtained from DB). If it is necessary, a * DOWN rounding operation is executed on the number. *

*
*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBigDecimalType implements UserType, ParameterizedType { private static final int sqlType = Types.NUMERIC; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private Integer decimalScale = null; private PBEBigDecimalEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigDecimal.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal storedEncryptedMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigDecimal scaledEncryptedMessage = storedEncryptedMessage.setScale( this.decimalScale.intValue(), BigDecimal.ROUND_UNNECESSARY); return this.encryptor.decrypt(scaledEncryptedMessage); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SessionImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigDecimal scaledValue = ((BigDecimal) value).setScale( this.decimalScale.intValue(), BigDecimal.ROUND_DOWN); final BigDecimal encryptedMessage = this.encryptor.encrypt(scaledValue); st.setBigDecimal(index, encryptedMessage); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramDecimalScale = parameters.getProperty(ParameterNaming.DECIMAL_SCALE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } if (paramDecimalScale != null) { try { this.decimalScale = new Integer(Integer.parseInt(paramDecimalScale)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.DECIMAL_SCALE + "\" is not a valid integer"); } } else { throw new EncryptionInitializationException( ParameterNaming.DECIMAL_SCALE + " must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigDecimalEncryptor pbeEncryptor = registry.getPBEBigDecimalEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big decimal encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigDecimalEncryptor newEncryptor = new StandardPBEBigDecimalEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigIntegerAsStringType.java000066400000000000000000000075561360667575700365070ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.math.BigInteger; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of BigInteger values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBigIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigInteger(string); } public Class returnedClass() { return BigInteger.class; } } EncryptedBigIntegerType.java000066400000000000000000000257321360667575700350300ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEBigIntegerEncryptor; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigInteger values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigIntegerEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigIntegerEncryptor (see * {@link HibernatePBEBigIntegerEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBigIntegerType implements UserType, ParameterizedType { private static int sqlType = Types.NUMERIC; private static int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEBigIntegerEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigInteger.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal decimalMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigInteger message = decimalMessage.setScale(0, BigDecimal.ROUND_UNNECESSARY). unscaledValue(); return this.encryptor.decrypt(message); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SessionImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigInteger encryptedMessage = this.encryptor.encrypt((BigInteger) value); st.setBigDecimal(index, new BigDecimal(encryptedMessage)); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigIntegerEncryptor pbeEncryptor = registry.getPBEBigIntegerEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigIntegerEncryptor newEncryptor = new StandardPBEBigIntegerEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBinaryType.java000066400000000000000000000321111360667575700342220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate4.encryptor.HibernatePBEByteEncryptor; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of byte[] values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEByteEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateByteEncryptor (see * {@link HibernatePBEByteEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBinaryType implements UserType, ParameterizedType { private static final int BLOCK_SIZE = 2048; private static final int sqlType = Types.VARBINARY; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEByteEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return byte[].class; } public boolean equals(final Object x, final Object y) throws HibernateException { return (x == y) || (x != null && y != null && java.util.Arrays.equals((byte[]) x, (byte[]) y)); } public Object deepCopy(final Object value) throws HibernateException { if (value == null) { return null; } final byte[] valueBytes = (byte[]) value; final byte[] copyBytes = new byte[valueBytes.length]; System.arraycopy(valueBytes, 0, copyBytes, 0, valueBytes.length); return copyBytes; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return true; } public int hashCode(final Object x) throws HibernateException { final byte[] valueBytes = (byte[]) x; int result = 1; for (int i = 0; i < valueBytes.length; i++ ) { result = (result * 17) + valueBytes[i]; } return result; } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return (original == null)? null : deepCopy(original); } public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); byte[] encryptedValue = null; if (Environment.useStreamsForBinary()) { final InputStream inputStream = rs.getBinaryStream(names[0]); if (rs.wasNull()) { return null; } final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BLOCK_SIZE); final byte[] inputBuff = new byte[BLOCK_SIZE]; try { int readBytes = 0; while (readBytes != -1) { readBytes = inputStream.read(inputBuff); if (readBytes != -1) { outputStream.write(inputBuff, 0, readBytes); } } } catch (IOException e) { throw new HibernateException( "IOException occurred reading a binary value", e); } finally { try { inputStream.close(); } catch (IOException e) { // exception ignored } try { outputStream.close(); } catch (IOException e) { // exception ignored } } encryptedValue = outputStream.toByteArray(); } else { encryptedValue = rs.getBytes(names[0]); if (rs.wasNull()) { return null; } } return this.encryptor.decrypt(encryptedValue); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SessionImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final byte[] encryptedValue = this.encryptor.encrypt((byte[]) value); if (Environment.useStreamsForBinary()) { st.setBinaryStream( index, new ByteArrayInputStream(encryptedValue), encryptedValue.length); } else { st.setBytes(index, encryptedValue); } } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEByteEncryptor pbeEncryptor = registry.getPBEByteEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEByteEncryptor newEncryptor = new StandardPBEByteEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBooleanAsStringType.java000066400000000000000000000074721360667575700360440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Boolean values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedBooleanAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return Boolean.valueOf(string); } public Class returnedClass() { return Boolean.class; } } EncryptedByteAsStringType.java000066400000000000000000000074311360667575700353630ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Byte values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedByteAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Byte(string); } public Class returnedClass() { return Byte.class; } } EncryptedCalendarAsStringType.java000066400000000000000000000134201360667575700361640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.util.Calendar; import java.util.Properties; import java.util.TimeZone; import org.jasypt.commons.CommonUtils; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Calendar values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* The boolean storeTimeZone parameter allows the Calendar to be * re-created with the same TimeZone that it was created. This is an * optional parameter, and its default value is FALSE. *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedCalendarAsStringType extends AbstractEncryptedAsStringType{ private Boolean storeTimeZone = Boolean.FALSE; /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final String[] stringTokens = CommonUtils.split(string); TimeZone tz = null; final long timeMillis = Long.valueOf(stringTokens[0]).longValue(); if (this.storeTimeZone.booleanValue()) { tz = TimeZone.getTimeZone(stringTokens[1]); } else { tz = TimeZone.getDefault(); } final Calendar cal = Calendar.getInstance(); cal.setTimeZone(tz); cal.setTimeInMillis(timeMillis); return cal; } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final StringBuffer strBuff = new StringBuffer(); final long timeMillis = ((Calendar) object).getTimeInMillis(); strBuff.append((new Long(timeMillis)).toString()); if (this.storeTimeZone.booleanValue()) { strBuff.append(" "); strBuff.append(((Calendar) object).getTimeZone().getID()); } return strBuff.toString(); } public synchronized void setParameterValues(final Properties parameters) { super.setParameterValues(parameters); final String paramStoreTimeZone = parameters.getProperty(ParameterNaming.STORE_TIME_ZONE); if ((paramStoreTimeZone != null) && (!paramStoreTimeZone.trim().equals(""))) { this.storeTimeZone = CommonUtils.getStandardBooleanValue(paramStoreTimeZone); } } public Class returnedClass() { return Calendar.class; } } EncryptedDateAsStringType.java000066400000000000000000000102231360667575700353260ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import java.util.Date; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Date values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedDateAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final long timeMillis = Long.valueOf(string).longValue(); return new Date(timeMillis); } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final long timeMillis = ((Date) object).getTime(); return String.valueOf(timeMillis); } public Class returnedClass() { return Date.class; } } EncryptedDoubleAsStringType.java000066400000000000000000000074551360667575700357000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Double values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedDoubleAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Double(string); } public Class returnedClass() { return Double.class; } } EncryptedFloatAsStringType.java000066400000000000000000000074441360667575700355310ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Float values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedFloatAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Float(string); } public Class returnedClass() { return Float.class; } } EncryptedIntegerAsStringType.java000066400000000000000000000074721360667575700360620ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Integer values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Integer(string); } public Class returnedClass() { return Integer.class; } } EncryptedLongAsStringType.java000066400000000000000000000074341360667575700353620ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Long values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedLongAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Long(string); } public Class returnedClass() { return Long.class; } } EncryptedShortAsStringType.java000066400000000000000000000074531360667575700355630ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows * encryption of Short values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedShortAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Short(string); } public Class returnedClass() { return Short.class; } } EncryptedStringType.java000066400000000000000000000073431360667575700342550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor; /** *

* A Hibernate UserType implementation which allows transparent * encryption of String values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptedStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String stringValue) { return stringValue; } public Class returnedClass() { return String.class; } } jasypt-jasypt-1.9.3/jasypt-hibernate4/src/main/java/org/jasypt/hibernate4/type/ParameterNaming.java000066400000000000000000000063261360667575700334200ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.type; /** *

* Constant names of the parameters that can be used by a jasypt type's * typedef declaration in a Hibernate mapping. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class ParameterNaming { /** *

* The registered name of an encryptor previously registered at the * {@link org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry}. *

*

* Value = encryptorRegisteredName *

*/ public static final String ENCRYPTOR_NAME = "encryptorRegisteredName"; /** *

* The encryption algorithm. *

*

* Value = algorithm *

*/ public static final String ALGORITHM = "algorithm"; /** *

* The name of the JCE security provider we want to get the algorithm from * (if it is no the default one. *

*

* Value = providerName *

*/ public static final String PROVIDER_NAME = "providerName"; /** *

* The encryption password. *

*

* Value = password *

*/ public static final String PASSWORD = "password"; /** *

* The number of hashing iterations to be applied for obtaining the * encryption key. *

*

* Value = keyObtentionIterations *

*/ public static final String KEY_OBTENTION_ITERATIONS = "keyObtentionIterations"; /** *

* The type of String output ("base64" (default), "hexadecimal") to be * generated. *

*

* Value = stringOutputType *

*/ public static final String STRING_OUTPUT_TYPE = "stringOutputType"; /** *

* The scale (numbers after the decimal point) to be used when storing * decimal numbers. *

*

* Value = decimalScale *

*/ public static final String DECIMAL_SCALE = "decimalScale"; /** *

* Whether the calendar time zone should be stored with the date or not. *

*

* Value = storeTimeZone *

*/ public static final String STORE_TIME_ZONE = "storeTimeZone"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/000077500000000000000000000000001360667575700214775ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/000077500000000000000000000000001360667575700224205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/000077500000000000000000000000001360667575700232075ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/000077500000000000000000000000001360667575700245215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/000077500000000000000000000000001360667575700265465ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/model/000077500000000000000000000000001360667575700276465ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/model/user/000077500000000000000000000000001360667575700306245ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/model/user/User.hbm.xml000066400000000000000000000027471360667575700330430ustar00rootroot00000000000000 hibernateStringEncryptor hibernateStringEncryptor hibernateByteEncryptor jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/model/user/User.java000066400000000000000000000045501360667575700324110ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.model.user; import java.util.Calendar; import org.apache.commons.lang.builder.ToStringBuilder; /** * * @author Soraya Sánchez * */ public class User { private String name; private String login; private String password; private Calendar birthdate; private byte[] document; public User(String name, String login, String password, Calendar birthdate, byte[] document) { super(); this.name = name; this.login = login; this.password = password; this.birthdate = birthdate; this.document = document; } public User() { super(); } public String toString() { return new ToStringBuilder(this).append("name", this.name) .append("login", this.login).append("password", this.password) .append("birthdate", this.birthdate) .append("document", this.document).toString(); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getLogin() { return this.login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Calendar getBirthdate() { return this.birthdate; } public void setBirthdate(Calendar birthdate) { this.birthdate = birthdate; } public byte[] getDocument() { return this.document; } public void setDocument(byte[] document) { this.document = document; } } jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/test/000077500000000000000000000000001360667575700275255ustar00rootroot00000000000000TestHibernateTypes.java000066400000000000000000000146321360667575700341050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate4/src/test/java/org/jasypt/hibernate4/test/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate4.test; import java.io.UnsupportedEncodingException; import java.sql.Connection; import java.sql.SQLException; import java.util.Calendar; import junit.framework.TestCase; import org.apache.commons.lang.RandomStringUtils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.Work; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.hibernate4.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate4.model.user.User; /** * * @author Soraya Sánchez * */ public class TestHibernateTypes extends TestCase { private static Configuration hbConf; private static SessionFactory sessionFactory; private static String userLogin; private static String userName; private static String userPassword; private static Calendar userBirthdate; private static byte[] userDocument; static Session session; public TestHibernateTypes() { super(); } public TestHibernateTypes(String name) { super(name); } public void testCreateAndReadUser() throws Exception { initialize(); createUser(); readUser(); finish(); } private void initialize() { registerEncryptors(); // Configure Hibernate and open session ServiceRegistryBuilder serviceRegistryBuilder = new ServiceRegistryBuilder() .applySetting("hibernate.dialect", "org.hibernate.dialect.HSQLDialect") .applySetting("hibernate.connection.url", "jdbc:hsqldb:mem:jasypttestdb") .applySetting("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver") .applySetting("hibernate.connection.username", "sa") .applySetting("hibernate.connection.password", "") .applySetting("hibernate.connection.pool_size", "10"); ServiceRegistry serviceRegistry = serviceRegistryBuilder.buildServiceRegistry(); hbConf = new Configuration(); sessionFactory = hbConf .addClass(User.class) .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect") .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:jasypttestdb") .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver") .setProperty("hibernate.connection.username", "sa") .setProperty("hibernate.connection.password", "") .setProperty("hibernate.connection.pool_size", "10") .buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); initDB(); generateData(); } private void registerEncryptors() { StandardPBEStringEncryptor stringEncryptor = new StandardPBEStringEncryptor(); stringEncryptor.setAlgorithm("PBEWithMD5AndDES"); stringEncryptor.setPassword("jasypt-hibernate3-test"); StandardPBEByteEncryptor byteEncryptor = new StandardPBEByteEncryptor(); byteEncryptor.setAlgorithm("PBEWithMD5AndDES"); byteEncryptor.setPassword("jasypt-hibernate3-test"); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("hibernateStringEncryptor", stringEncryptor); registry.registerPBEByteEncryptor("hibernateByteEncryptor", byteEncryptor); } /** * Create db structure */ private void initDB() { Transaction transaction = session.beginTransaction(); session.doWork(new Work() { public void execute(Connection connection) throws SQLException { connection.createStatement().execute( "CREATE MEMORY TABLE PUBLIC.USER(" + "NAME VARCHAR(100)," + "LOGIN VARCHAR(100) PRIMARY KEY," + "PASSWORD VARCHAR(100)," + "BIRTHDATE VARCHAR(100)," + "DOCUMENT BLOB);"); } }); transaction.commit(); } /** * Generate data to test with */ private void generateData() { userLogin = RandomStringUtils.randomAlphabetic(5); userName = RandomStringUtils.randomAlphabetic(10); userPassword = RandomStringUtils.randomAlphanumeric(15); userBirthdate = Calendar.getInstance(); try { userDocument = RandomStringUtils.randomAlphabetic(100).getBytes( "ISO-8859-1"); } catch (UnsupportedEncodingException e) { assertTrue(false); } } private void finish() { session.close(); } private void createUser() throws Exception { User user = new User(userName, userLogin, userPassword, userBirthdate, userDocument); Transaction transaction = session.beginTransaction(); session.saveOrUpdate(user); System.out.println("User stored: " + user); transaction.commit(); assertTrue(true); } private void readUser() throws Exception { Transaction transaction = session.beginTransaction(); User user = (User) session.load(User.class, userLogin); System.out.println("User read: " + user); transaction.commit(); assertEquals(user.getLogin(), userLogin); assertEquals(user.getName(), userName); assertEquals(user.getPassword(), userPassword); assertEquals(user.getBirthdate(), userBirthdate); assertEquals(user.getDocument(), userDocument); } } jasypt-jasypt-1.9.3/jasypt-hibernate5/000077500000000000000000000000001360667575700177325ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/.gitignore000066400000000000000000000000721360667575700217210ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-hibernate5/BUILD.txt000066400000000000000000000015511360667575700213340ustar00rootroot00000000000000 Building JASYPT-HIBERNATE5 -------------------------- To build JASYPT-HIBERNATE5 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-HIBERNATE5 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-hibernate5-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-hibernate5/{version}/jasypt-hibernate5-{version}.jar Generating Javadoc for JASYPT-HIBERNATE5 ---------------------------------------- If you wish to generate the javadoc for JASYPT-HIBERNATE, execute this from the JASYPT-HIBERNATE5 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-hibernate5/ChangeLog.txt000066400000000000000000000001571360667575700223250ustar00rootroot000000000000001.9.3 ===== - Created new jasypt-hibernate5 module for Hibernate 5 integration. - Created additional testsjasypt-jasypt-1.9.3/jasypt-hibernate5/LICENSE.txt000066400000000000000000000264501360667575700215640ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-hibernate5/NOTICE.txt000066400000000000000000000074211360667575700214600ustar00rootroot00000000000000 Copyright (c) 2007-2017, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-hibernate5/README.txt000066400000000000000000000006261360667575700214340ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-hibernate5/RELEASING.txt000066400000000000000000000023501360667575700220040ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-hibernate5/USAGE.txt000066400000000000000000000012271360667575700213410ustar00rootroot00000000000000 Using JASYPT-HIBERNATE5 from Maven 2 ------------------------------------ In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-hibernate5 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-hibernate5/pom.xml000066400000000000000000000205711360667575700212540ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-hibernate5 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD chuspicosvilar Chus Picos chuspicosvilar AT users.sourceforge.net Developer hokitorres Hoki Torres hokitorres AT users.sourceforge.net Developer sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true jboss-nexus-repository JBoss Nexus Repository http://repository.jboss.org/nexus/content/groups/public-jboss/ src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/java ** **/*.java src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.8.0 1.8 1.8 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.1 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.hibernate hibernate-core 5.2.5.Final provided true org.hibernate hibernate-c3p0 5.2.5.Final provided true org.hibernate hibernate-testing 5.2.5.Final test true junit junit 3.8.1 test commons-lang commons-lang 2.1 test org.hsqldb hsqldb 2.2.6 test jasypt-jasypt-1.9.3/jasypt-hibernate5/src/000077500000000000000000000000001360667575700205215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/000077500000000000000000000000001360667575700214455ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/000077500000000000000000000000001360667575700223665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/000077500000000000000000000000001360667575700231555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/000077500000000000000000000000001360667575700244675ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/000077500000000000000000000000001360667575700265155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/connectionprovider/000077500000000000000000000000001360667575700324275ustar00rootroot00000000000000EncryptedPasswordC3P0ConnectionProvider.java000066400000000000000000000127631360667575700430250ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.connectionprovider; import java.util.Properties; import org.hibernate.c3p0.internal.C3P0ConnectionProvider; import org.hibernate.cfg.AvailableSettings; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link C3P0ConnectionProvider} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordC3P0ConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="c3p0.min_size">5</property>
 *      <property name="c3p0.max_size">20</property>
 *      <property name="c3p0.timeout">1800</property>
 *      <property name="c3p0.max_statements">50</property>
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedPasswordC3P0ConnectionProvider extends C3P0ConnectionProvider { private static final long serialVersionUID = 5273353009914873806L; public EncryptedPasswordC3P0ConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(AvailableSettings.DRIVER); final String url = props.getProperty(AvailableSettings.URL); final String user = props.getProperty(AvailableSettings.USER); final String password = props.getProperty(AvailableSettings.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( AvailableSettings.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( AvailableSettings.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( AvailableSettings.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( AvailableSettings.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate do the rest super.configure(props); } } EncryptedPasswordDriverManagerConnectionProvider.java000066400000000000000000000126371360667575700451060ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.connectionprovider; import java.util.Properties; import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.properties.PropertyValueEncryptionUtils; /** * *

* Extension of {@link DriverManagerConnectionProviderImpl} that allows the user * to write the datasource configuration parameters in an encrypted manner in the * hibernate.cfg.xml or hibernate.properties file *

*

* The encryptable parameters are: *

    *
  • connection.driver_class
  • *
  • connection.url
  • *
  • connection.username
  • *
  • connection.password
  • *
*

*

* The name of the password encryptor (decryptor, in fact) will be set in * property hibernate.connection.encryptor_registered_name. * Its value must be the name of a {@link PBEStringEncryptor} object * previously registered within {@link HibernatePBEEncryptorRegistry}. *

*

* An example hibernate.cfg.xml file: *

*

*

 *  <hibernate-configuration>
 *
 *    <session-factory>
 *
 *      <!-- Database connection settings -->
 *      <property name="connection.provider_class">org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider</property>
 *      <property name="connection.encryptor_registered_name">stringEncryptor</property>
 *      <property name="connection.driver_class">org.postgresql.Driver</property>
 *      <property name="connection.url">jdbc:postgresql://localhost/mydatabase</property>
 *      <property name="connection.username">myuser</property>
 *      <property name="connection.password">ENC(T6DAe34NasW==)</property>
 *      <property name="connection.pool_size">5</property>
 *      
 *      ...
 *      
 *    </session-factory>
 *    
 *    ...
 *    
 *  </hibernate-configuration>
 * 
*

* * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedPasswordDriverManagerConnectionProvider extends DriverManagerConnectionProviderImpl { private static final long serialVersionUID = 7409509667904250297L; public EncryptedPasswordDriverManagerConnectionProvider() { super(); } public void configure(final Properties props) { final String encryptorRegisteredName = props.getProperty(ParameterNaming.ENCRYPTOR_REGISTERED_NAME); final HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor encryptor = encryptorRegistry.getPBEStringEncryptor(encryptorRegisteredName); if (encryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + encryptorRegisteredName + "\""); } // Get the original values, which may be encrypted final String driver = props.getProperty(AvailableSettings.DRIVER); final String url = props.getProperty(AvailableSettings.URL); final String user = props.getProperty(AvailableSettings.USER); final String password = props.getProperty(AvailableSettings.PASS); // Perform decryption operations as needed and store the new values if (PropertyValueEncryptionUtils.isEncryptedValue(driver)) { props.setProperty( AvailableSettings.DRIVER, PropertyValueEncryptionUtils.decrypt(driver, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(url)) { props.setProperty( AvailableSettings.URL, PropertyValueEncryptionUtils.decrypt(url, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(user)) { props.setProperty( AvailableSettings.USER, PropertyValueEncryptionUtils.decrypt(user, encryptor)); } if (PropertyValueEncryptionUtils.isEncryptedValue(password)) { props.setProperty( AvailableSettings.PASS, PropertyValueEncryptionUtils.decrypt(password, encryptor)); } // Let Hibernate process super.configure(props); } } ParameterNaming.java000066400000000000000000000030171360667575700362660ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/connectionprovider/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.connectionprovider; /** *

* Constant names of the parameters that can be used by a jasypt's * Hibernate connection provider. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class ParameterNaming { /** * Property in hibernate.cfg.xml or * hibernate.properties which contains the registered name * (in {@link HibernatePBEEncryptorRegistry}) of the encryptor which * will be used to decrypt the datasource parameters. */ public static final String ENCRYPTOR_REGISTERED_NAME = "hibernate.connection.encryptor_registered_name"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/000077500000000000000000000000001360667575700305425ustar00rootroot00000000000000HibernatePBEBigDecimalEncryptor.java000066400000000000000000000332571360667575700373770ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.encryptor; import java.math.BigDecimal; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigDecimalEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigDecimalEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigDecimalEncryptor be explicitly set * with {@link #setEncryptor(PBEBigDecimalEncryptor)}. If not, a * StandardPBEBigDecimalEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigDecimalEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigDecimalEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigDecimalEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigDecimalEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigDecimalEncryptor * objects this way to wrap PBEBigDecimalEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigDecimalEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class HibernatePBEBigDecimalEncryptor { private String registeredName = null; private PBEBigDecimalEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigDecimalEncryptor It also * creates a StandardPBEBigDecimalEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigDecimalEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigDecimalEncryptor * is registered programmatically. */ HibernatePBEBigDecimalEncryptor(final String registeredName, final PBEBigDecimalEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigDecimalEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigDecimalEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigDecimalEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigDecimalEncryptor standardPBEBigDecimalEncryptor = (StandardPBEBigDecimalEncryptor) this.encryptor; standardPBEBigDecimalEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigDecimal encrypt(final BigDecimal message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigDecimal decrypt(final BigDecimal encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigDecimalEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigDecimalEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEBigIntegerEncryptor.java000066400000000000000000000331661360667575700374350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.encryptor; import java.math.BigInteger; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEBigIntegerEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEBigIntegerEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEBigIntegerEncryptor be explicitly set * with {@link #setEncryptor(PBEBigIntegerEncryptor)}. If not, a * StandardPBEBigIntegerEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="bigIntegerEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEBigIntegerEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateBigIntegerEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="bigIntegerEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEBigIntegerEncryptor * objects this way to wrap PBEBigIntegerEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEBigIntegerEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class HibernatePBEBigIntegerEncryptor { private String registeredName = null; private PBEBigIntegerEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEBigIntegerEncryptor It also * creates a StandardPBEBigIntegerEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEBigIntegerEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEBigIntegerEncryptor * is registered programmatically. */ HibernatePBEBigIntegerEncryptor(final String registeredName, final PBEBigIntegerEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEBigIntegerEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEBigIntegerEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEBigIntegerEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEBigIntegerEncryptor standardPBEBigIntegerEncryptor = (StandardPBEBigIntegerEncryptor) this.encryptor; standardPBEBigIntegerEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public BigInteger encrypt(final BigInteger message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public BigInteger decrypt(final BigInteger encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEBigIntegerEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEBigIntegerEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEByteEncryptor.java000066400000000000000000000323451360667575700363170ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.encryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEByteEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEByteEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEByteEncryptor be explicitly set * with {@link #setEncryptor(PBEByteEncryptor)}. If not, a * StandardPBEByteEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 
 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="byteEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEByteEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEByteEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateByteEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="byteEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEByteEncryptor * objects this way to wrap PBEByteEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEByteEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class HibernatePBEByteEncryptor { private String registeredName = null; private PBEByteEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEByteEncryptor It also * creates a StandardPBEByteEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEByteEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEByteEncryptor * is registered programmatically. */ HibernatePBEByteEncryptor(final String registeredName, final PBEByteEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public PBEByteEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEByteEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public void setEncryptor(final PBEByteEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setIvGenerator(ivGenerator); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEByteEncryptor standardPBEByteEncryptor = (StandardPBEByteEncryptor) this.encryptor; standardPBEByteEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public byte[] encrypt(final byte[] message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public byte[] decrypt(final byte[] encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEByteEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEByteEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } HibernatePBEEncryptorRegistry.java000066400000000000000000000263601360667575700372240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.encryptor; import java.util.HashMap; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Registry for all the PBE*Encryptor which are eligible for * use from Hibernate. *

*

* This class is intended to be directly used in applications where * an IoC container (like Spring Framework) is not present. If it is, * it is better to use the HibernatePBE*Encryptor classes * directly, instead. *

*

* This registry is a singleton which maintains a registry * of PBE*Encryptor objects which can be used from Hibernate, * by using its registeredName to reference them from mappings. *

*

* The steps would be: *

    *
  1. Obtain the registry instance ({@link #getInstance()}).
  2. *
  3. Register the encryptor, giving it a registered name * (registerPBE*Encryptor(String, PBE*Encryptor).
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * when registering the encryptor.
  6. *
*

*

* This is, first register the encryptor (example with a String encryptor): *

*

*

 *  StandardPBEStringEncryptor myEncryptor = new StandardPBEStringEncryptor();
 *  ...
 *  HibernatePBEEncryptorRegistry registry =
 *      HibernatePBEEncryptorRegistry.getInstance();
 *  registry.registerPBEStringEncryptor("myHibernateEncryptor", myEncryptor);
 * 
*

*

* And then, reference it from a Hibernate mapping file: *

*

*

 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateEncryptor</param>
 *    </typedef>
 * 
*

* * * @since 1.9.0 * * @author Chus Picos * */ public final class HibernatePBEEncryptorRegistry { // The singleton instance private static final HibernatePBEEncryptorRegistry instance = new HibernatePBEEncryptorRegistry(); // Registry maps private final HashMap stringEncryptors = new HashMap(); private final HashMap bigIntegerEncryptors = new HashMap(); private final HashMap bigDecimalEncryptors = new HashMap(); private final HashMap byteEncryptors = new HashMap(); /** * Returns the singleton instance of the registry. * * @return the registry. */ public static HibernatePBEEncryptorRegistry getInstance() { return instance; } // The registry cannot be externally instantiated. private HibernatePBEEncryptorRegistry() { super(); } /** * Registers a PBEStringEncryptor object with the specified * name. * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEStringEncryptor( final String registeredName, final PBEStringEncryptor encryptor) { final HibernatePBEStringEncryptor hibernateEncryptor = new HibernatePBEStringEncryptor(registeredName, encryptor); this.stringEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void registerHibernatePBEStringEncryptor( final HibernatePBEStringEncryptor hibernateEncryptor) { this.stringEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEStringEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEStringEncryptor(final String name) { this.stringEncryptors.remove(name); } /** * Returns the PBEStringEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEStringEncryptor getPBEStringEncryptor( final String registeredName) { final HibernatePBEStringEncryptor hibernateEncryptor = (HibernatePBEStringEncryptor) this.stringEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigIntegerEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigIntegerEncryptor( final String registeredName, final PBEBigIntegerEncryptor encryptor) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = new HibernatePBEBigIntegerEncryptor(registeredName, encryptor); this.bigIntegerEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigIntegerEncryptor( final HibernatePBEBigIntegerEncryptor hibernateEncryptor) { this.bigIntegerEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigIntegerEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigIntegerEncryptor(final String name) { this.bigIntegerEncryptors.remove(name); } /** * Returns the PBEBigIntegerEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigIntegerEncryptor getPBEBigIntegerEncryptor( final String registeredName) { final HibernatePBEBigIntegerEncryptor hibernateEncryptor = (HibernatePBEBigIntegerEncryptor) this.bigIntegerEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEBigDecimalEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEBigDecimalEncryptor( final String registeredName, final PBEBigDecimalEncryptor encryptor) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = new HibernatePBEBigDecimalEncryptor(registeredName, encryptor); this.bigDecimalEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void registerHibernatePBEBigDecimalEncryptor( final HibernatePBEBigDecimalEncryptor hibernateEncryptor) { this.bigDecimalEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEBigDecimalEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEBigDecimalEncryptor(final String name) { this.bigDecimalEncryptors.remove(name); } /** * Returns the PBEBigDecimalEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEBigDecimalEncryptor getPBEBigDecimalEncryptor( final String registeredName) { final HibernatePBEBigDecimalEncryptor hibernateEncryptor = (HibernatePBEBigDecimalEncryptor) this.bigDecimalEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } /** * Registers a PBEByteEncryptor object with the specified * name. * * @since 1.6 * * @param registeredName the registered name. * @param encryptor the encryptor to be registered. */ public synchronized void registerPBEByteEncryptor( final String registeredName, final PBEByteEncryptor encryptor) { final HibernatePBEByteEncryptor hibernateEncryptor = new HibernatePBEByteEncryptor(registeredName, encryptor); this.byteEncryptors.put(registeredName, hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void registerHibernatePBEByteEncryptor( final HibernatePBEByteEncryptor hibernateEncryptor) { this.byteEncryptors.put( hibernateEncryptor.getRegisteredName(), hibernateEncryptor); } // Not public: this is used from // HibernatePBEByteEncryptor.setRegisteredName. synchronized void unregisterHibernatePBEByteEncryptor(final String name) { this.byteEncryptors.remove(name); } /** * Returns the PBEByteEncryptor registered with the specified * name (if exists). * * @param registeredName the name with which the desired encryptor was * registered. * @return the encryptor, or null if no encryptor has been registered with * that name. */ public synchronized PBEByteEncryptor getPBEByteEncryptor( final String registeredName) { final HibernatePBEByteEncryptor hibernateEncryptor = (HibernatePBEByteEncryptor) this.byteEncryptors.get(registeredName); if (hibernateEncryptor == null) { return null; } return hibernateEncryptor.getEncryptor(); } } HibernatePBEStringEncryptor.java000066400000000000000000000375021360667575700366620ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/encryptor/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.encryptor; import java.security.Provider; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Placeholder class for PBEStringEncryptor objects which are * eligible for use from Hibernate. *

*

* This class acts as a wrapper on a PBEStringEncryptor, allowing * to be set a registered name (see {@link #setRegisteredName(String)}) * and performing the needed registry operations against the * {@link HibernatePBEEncryptorRegistry}. *

*

* It is not mandatory that a PBEStringEncryptor be explicitly set * with {@link #setEncryptor(PBEStringEncryptor)}. If not, a * StandardPBEStringEncryptor object will be created internally * and it will be configurable with the * {@link #setPassword(String)}/{@link #setPasswordCharArray(char[])}, * {@link #setAlgorithm(String)}, {@link #setKeyObtentionIterations(int)}, * {@link #setSaltGenerator(SaltGenerator)}, {@link #setIvGenerator(IvGenerator)}, * {@link #setProviderName(String)}, * {@link #setProvider(Provider)}, {@link #setStringOutputType(String)} * and {@link #setConfig(PBEConfig)} methods. *

*

* This class is mainly intended for use from Spring Framework or some other * IoC container (if you are not using a container of this kind, please see * {@link HibernatePBEEncryptorRegistry}). The steps to be performed are * the following: *

    *
  1. Create an object of this class (declaring it).
  2. *
  3. Set its registeredName and, either its * wrapped encryptor or its password, * algorithm, keyObtentionIterations, * saltGenerator, ivGenerator and config properties.
  4. *
  5. Declare a typedef in a Hibernate mapping giving its * encryptorRegisteredName parameter the same value specified * to this object in registeredName.
  6. *
*

*

* This in a Spring config file would look like: *

*

*

 *  ...
 *  <-- Optional, as the hibernateEncryptor could be directly set an     -->
 *  <-- algorithm and password.                                          -->
 *  <bean id="stringEncryptor"
 *    class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
 *    <property name="algorithm">
 *        <value>PBEWithMD5AndDES</value>
 *    </property>
 *    <property name="password">
 *        <value>XXXXX</value>
 *    </property>
 *  </bean>
 *  
 *  <bean id="hibernateEncryptor"
 *    class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
 *    <property name="registeredName">
 *        <value>myHibernateStringEncryptor</value>
 *    </property>
 *    <property name="encryptor">
 *        <ref bean="stringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 * 
*

*

* And then in the Hibernate mapping file: *

*

*

 *    <typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 * 
*

*

* An important thing to note is that, when using HibernatePBEStringEncryptor * objects this way to wrap PBEStringEncryptors, it is not * necessary to deal with {@link HibernatePBEEncryptorRegistry}, * because HibernatePBEStringEncryptor objects get automatically registered * in the encryptor registry when their {@link #setRegisteredName(String)} * method is called. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class HibernatePBEStringEncryptor { private String registeredName = null; private PBEStringEncryptor encryptor = null; private boolean encryptorSet = false; /** * Creates a new instance of HibernatePBEStringEncryptor. It also * creates a StandardPBEStringEncryptor for internal use, which * can be overriden by calling setEncryptor(...). */ public HibernatePBEStringEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptorSet = false; } /* * For internal use only, by the Registry, when a PBEStringEncryptor * is registered programmatically. */ HibernatePBEStringEncryptor(final String registeredName, final PBEStringEncryptor encryptor) { this.encryptor = encryptor; this.registeredName = registeredName; this.encryptorSet = true; } /** * Returns the encryptor which this object wraps. * * @return the encryptor. */ public synchronized PBEStringEncryptor getEncryptor() { return this.encryptor; } /** * Sets the PBEStringEncryptor to be held (wrapped) by this * object. This method is optional and can be only called once. * * @param encryptor the encryptor. */ public synchronized void setEncryptor(final PBEStringEncryptor encryptor) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } this.encryptor = encryptor; this.encryptorSet = true; } /** * Sets the password to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param password the password to be set for the internal encryptor */ public void setPassword(final String password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPassword(password); } /** * Sets the password to be used by the internal encryptor (as a char[]), if a specific * encryptor has not been set with setEncryptor(...). * * @since 1.8 * @param password the password to be set for the internal encryptor */ public void setPasswordCharArray(final char[] password) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setPasswordCharArray(password); } /** * Sets the algorithm to be used by the internal encryptor, if a specific * encryptor has not been set with setEncryptor(...). * * @param algorithm the algorithm to be set for the internal encryptor */ public void setAlgorithm(final String algorithm) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setAlgorithm(algorithm); } /** * Sets the key obtention iterations to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param keyObtentionIterations to be set for the internal encryptor */ public void setKeyObtentionIterations(final int keyObtentionIterations) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setKeyObtentionIterations( keyObtentionIterations); } /** * Sets the salt generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param saltGenerator the salt generator to be set for the internal * encryptor. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setSaltGenerator(saltGenerator); } /** * Sets the IV generator to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param ivGenerator the IV generator to be set for the internal * encryptor. */ public void setIvGenerator(final IvGenerator ivGenerator) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setIvGenerator(ivGenerator); } /** * Sets the name of the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param providerName the name of the JCE provider (already registered) */ public void setProviderName(final String providerName) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProviderName(providerName); } /** * Sets the JCE provider to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param provider the JCE provider to be used */ public void setProvider(final Provider provider) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setProvider(provider); } /** * Sets the type of String output ("base64" (default), "hexadecimal") to * be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @since 1.3 * * @param stringOutputType the type of String output */ public void setStringOutputType(final String stringOutputType) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setStringOutputType(stringOutputType); } /** * Sets the PBEConfig to be used by the internal encryptor, * if a specific encryptor has not been set with setEncryptor(...). * * @param config the PBEConfig to be set for the internal encryptor */ public void setConfig(final PBEConfig config) { if (this.encryptorSet) { throw new EncryptionInitializationException( "An encryptor has been already set: no " + "further configuration possible on hibernate wrapper"); } final StandardPBEStringEncryptor standardPBEStringEncryptor = (StandardPBEStringEncryptor) this.encryptor; standardPBEStringEncryptor.setConfig(config); } /** * Encrypts a message, delegating to wrapped encryptor. * * @param message the message to be encrypted. * @return the encryption result. */ public String encrypt(final String message) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.encrypt(message); } /** * Decypts a message, delegating to wrapped encryptor * * @param encryptedMessage the message to be decrypted. * @return the result of decryption. */ public String decrypt(final String encryptedMessage) { if (this.encryptor == null) { throw new EncryptionInitializationException( "Encryptor has not been set into Hibernate wrapper"); } return this.encryptor.decrypt(encryptedMessage); } /** * Sets the registered name of the encryptor and adds it to the registry. * * @param registeredName the name with which the encryptor will be * registered. */ public void setRegisteredName(final String registeredName) { if (this.registeredName != null) { // It had another name before, we have to clean HibernatePBEEncryptorRegistry.getInstance(). unregisterHibernatePBEStringEncryptor(this.registeredName); } this.registeredName = registeredName; HibernatePBEEncryptorRegistry.getInstance(). registerHibernatePBEStringEncryptor(this); } /** * Returns the name with which the wrapped encryptor is registered at * the registry. * * @return the registered name. */ public String getRegisteredName() { return this.registeredName; } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/000077500000000000000000000000001360667575700274765ustar00rootroot00000000000000AbstractEncryptedAsStringType.java000066400000000000000000000233631360667575700362270ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; /** * * Base class for Hibernate UserTypes to store * values as encrypted strings. * * @since 1.9.0 * @author Chus Picos * */ public abstract class AbstractEncryptedAsStringType implements UserType, ParameterizedType { static final int sqlType = Types.VARCHAR; static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String providerName = null; private String password = null; private Integer keyObtentionIterations = null; private String stringOutputType = null; protected PBEStringEncryptor encryptor = null; /** * Converts given String to its Object form. * @param string the string value * @return the object form of the passed String */ protected abstract Object convertToObject(final String string); /** * Converts given Object to its String form. * @param object the object value * @return the string form of the passes Object */ protected String convertToString(final Object object) { return object == null? null : object.toString(); } public final int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public abstract Class returnedClass(); public final boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public final Object deepCopy(final Object value) throws HibernateException { return value; } public final Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public final Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public final boolean isMutable() { return false; } public final int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public final Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SharedSessionContractImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final String message = rs.getString(names[0]); return rs.wasNull() ? null : convertToObject(this.encryptor.decrypt(message)); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SharedSessionContractImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { st.setString(index, this.encryptor.encrypt(convertToString(value))); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramProviderName = parameters.getProperty(ParameterNaming.PROVIDER_NAME); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramStringOutputType = parameters.getProperty(ParameterNaming.STRING_OUTPUT_TYPE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramProviderName != null) { this.providerName = paramProviderName; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } if (paramStringOutputType != null) { this.stringOutputType = paramStringOutputType; } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } protected synchronized final void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEStringEncryptor pbeEncryptor = registry.getPBEStringEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No string encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEStringEncryptor newEncryptor = new StandardPBEStringEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.providerName != null) { newEncryptor.setProviderName(this.providerName); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } if (this.stringOutputType != null) { newEncryptor.setStringOutputType(this.stringOutputType); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigDecimalAsStringType.java000066400000000000000000000073261360667575700364450ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.math.BigDecimal; /** *

* A Hibernate UserType implementation which allows * encryption of BigDecimal values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimalAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBigDecimalAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigDecimal(string); } public Class returnedClass() { return BigDecimal.class; } } EncryptedBigDecimalType.java000066400000000000000000000321351360667575700347660ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.io.Serializable; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigDecimal values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="encryptorRegisteredName">myHibernateBigDecimalEncryptor</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigDecimalEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigDecimalEncryptor (see * {@link HibernatePBEBigDecimalEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="decimalScale">2</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigDecimal" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

*

* About the decimalScale parameter *

* The decimalScale parameter is aimed at setting the scale with which * BigDecimal numbers will be set to and retrieved from the database. It is * an important parameter because many DBMSs return BigDecimal numbers with * a scale equal to the amount of decimal positions declared for the field * (e.g. if we store "18.23" (scale=2) in a DECIMAL(15,5) field, we can get a * "18.23000" (scale=5) back when we retrieve the number). This can affect * correct decryption of encrypted numbers, but specifying a * decimalScale parameter will solve this issue. *

*

* So, if we set decimalScale to 3, and we store "18.23", this * Hibernate type will send "18.230" to the encryptor, which is the value that * we will get back from the database at retrieval time (a scale of "3" * will be set again on the value obtained from DB). If it is necessary, a * DOWN rounding operation is executed on the number. *

*
*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBigDecimalType implements UserType, ParameterizedType { private static final int sqlType = Types.NUMERIC; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private Integer decimalScale = null; private PBEBigDecimalEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigDecimal.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SharedSessionContractImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal storedEncryptedMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigDecimal scaledEncryptedMessage = storedEncryptedMessage.setScale( this.decimalScale.intValue(), BigDecimal.ROUND_UNNECESSARY); return this.encryptor.decrypt(scaledEncryptedMessage); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SharedSessionContractImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigDecimal scaledValue = ((BigDecimal) value).setScale( this.decimalScale.intValue(), BigDecimal.ROUND_DOWN); final BigDecimal encryptedMessage = this.encryptor.encrypt(scaledValue); st.setBigDecimal(index, encryptedMessage); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); final String paramDecimalScale = parameters.getProperty(ParameterNaming.DECIMAL_SCALE); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } if (paramDecimalScale != null) { try { this.decimalScale = new Integer(Integer.parseInt(paramDecimalScale)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.DECIMAL_SCALE + "\" is not a valid integer"); } } else { throw new EncryptionInitializationException( ParameterNaming.DECIMAL_SCALE + " must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigDecimalEncryptor pbeEncryptor = registry.getPBEBigDecimalEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big decimal encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigDecimalEncryptor newEncryptor = new StandardPBEBigDecimalEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBigIntegerAsStringType.java000066400000000000000000000073261360667575700365040ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.math.BigInteger; /** *

* A Hibernate UserType implementation which allows * encryption of BigInteger values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBigIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new BigInteger(string); } public Class returnedClass() { return BigInteger.class; } } EncryptedBigIntegerType.java000066400000000000000000000256571360667575700350400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of BigInteger values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="encryptorRegisteredName">myHibernateBigIntegerEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEBigIntegerEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateBigIntegerEncryptor (see * {@link HibernatePBEBigIntegerEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedBigInteger" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBigIntegerType implements UserType, ParameterizedType { private static int sqlType = Types.NUMERIC; private static int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEBigIntegerEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return BigInteger.class; } public boolean equals(final Object x, final Object y) throws HibernateException { return x == y || ( x != null && y != null && x.equals( y ) ); } public Object deepCopy(final Object value) throws HibernateException { return value; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return false; } public int hashCode(final Object x) throws HibernateException { return x.hashCode(); } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return original; } public Object nullSafeGet(final ResultSet rs, final String[] names, final SharedSessionContractImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); final BigDecimal decimalMessage = rs.getBigDecimal(names[0]); if (rs.wasNull()) { return null; } final BigInteger message = decimalMessage.setScale(0, BigDecimal.ROUND_UNNECESSARY). unscaledValue(); return this.encryptor.decrypt(message); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SharedSessionContractImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final BigInteger encryptedMessage = this.encryptor.encrypt((BigInteger) value); st.setBigDecimal(index, new BigDecimal(encryptedMessage)); } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEBigIntegerEncryptor pbeEncryptor = registry.getPBEBigIntegerEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEBigIntegerEncryptor newEncryptor = new StandardPBEBigIntegerEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBinaryType.java000066400000000000000000000320441360667575700342310ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; /** *

* A Hibernate UserType implementation which allows transparent * encryption of byte[] values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="encryptorRegisteredName">myHibernateByteEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEByteEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateByteEncryptor (see * {@link HibernatePBEByteEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="resume" column="RESUME" type="encryptedBinary" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBinaryType implements UserType, ParameterizedType { private static final int BLOCK_SIZE = 2048; private static final int sqlType = Types.VARBINARY; private static final int[] sqlTypes = new int[]{ sqlType }; private boolean initialized = false; private boolean useEncryptorName = false; private String encryptorName = null; private String algorithm = null; private String password = null; private Integer keyObtentionIterations = null; private PBEByteEncryptor encryptor = null; public int[] sqlTypes() { return (int[]) sqlTypes.clone(); } public Class returnedClass() { return byte[].class; } public boolean equals(final Object x, final Object y) throws HibernateException { return (x == y) || (x != null && y != null && java.util.Arrays.equals((byte[]) x, (byte[]) y)); } public Object deepCopy(final Object value) throws HibernateException { if (value == null) { return null; } final byte[] valueBytes = (byte[]) value; final byte[] copyBytes = new byte[valueBytes.length]; System.arraycopy(valueBytes, 0, copyBytes, 0, valueBytes.length); return copyBytes; } public Object assemble(final Serializable cached, final Object owner) throws HibernateException { if (cached == null) { return null; } return deepCopy(cached); } public Serializable disassemble(final Object value) throws HibernateException { if (value == null) { return null; } return (Serializable) deepCopy(value); } public boolean isMutable() { return true; } public int hashCode(final Object x) throws HibernateException { final byte[] valueBytes = (byte[]) x; int result = 1; for (int i = 0; i < valueBytes.length; i++ ) { result = (result * 17) + valueBytes[i]; } return result; } public Object replace(final Object original, final Object target, final Object owner) throws HibernateException { return (original == null)? null : deepCopy(original); } public Object nullSafeGet(final ResultSet rs, final String[] names, final SharedSessionContractImplementor session, final Object owner) throws HibernateException, SQLException { checkInitialization(); byte[] encryptedValue = null; if (Environment.useStreamsForBinary()) { final InputStream inputStream = rs.getBinaryStream(names[0]); if (rs.wasNull()) { return null; } final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BLOCK_SIZE); final byte[] inputBuff = new byte[BLOCK_SIZE]; try { int readBytes = 0; while (readBytes != -1) { readBytes = inputStream.read(inputBuff); if (readBytes != -1) { outputStream.write(inputBuff, 0, readBytes); } } } catch (IOException e) { throw new HibernateException( "IOException occurred reading a binary value", e); } finally { try { inputStream.close(); } catch (IOException e) { // exception ignored } try { outputStream.close(); } catch (IOException e) { // exception ignored } } encryptedValue = outputStream.toByteArray(); } else { encryptedValue = rs.getBytes(names[0]); if (rs.wasNull()) { return null; } } return this.encryptor.decrypt(encryptedValue); } public void nullSafeSet(final PreparedStatement st, final Object value, final int index, final SharedSessionContractImplementor session) throws HibernateException, SQLException { checkInitialization(); if (value == null) { st.setNull(index, sqlType); } else { final byte[] encryptedValue = this.encryptor.encrypt((byte[]) value); if (Environment.useStreamsForBinary()) { st.setBinaryStream( index, new ByteArrayInputStream(encryptedValue), encryptedValue.length); } else { st.setBytes(index, encryptedValue); } } } public synchronized void setParameterValues(final Properties parameters) { final String paramEncryptorName = parameters.getProperty(ParameterNaming.ENCRYPTOR_NAME); final String paramAlgorithm = parameters.getProperty(ParameterNaming.ALGORITHM); final String paramPassword = parameters.getProperty(ParameterNaming.PASSWORD); final String paramKeyObtentionIterations = parameters.getProperty(ParameterNaming.KEY_OBTENTION_ITERATIONS); this.useEncryptorName = false; if (paramEncryptorName != null) { if ((paramAlgorithm != null) || (paramPassword != null) || (paramKeyObtentionIterations != null)) { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is specified, none of \"" + ParameterNaming.ALGORITHM + "\", \"" + ParameterNaming.PASSWORD + "\" or \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" " + "can be specified"); } this.encryptorName = paramEncryptorName; this.useEncryptorName = true; } else if ((paramPassword != null)) { this.password = paramPassword; if (paramAlgorithm != null) { this.algorithm = paramAlgorithm; } if (paramKeyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer( Integer.parseInt(paramKeyObtentionIterations)); } catch (NumberFormatException e) { throw new EncryptionInitializationException( "Value specified for \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\" is not a valid integer"); } } } else { throw new EncryptionInitializationException( "If \"" + ParameterNaming.ENCRYPTOR_NAME + "\" is not specified, then \"" + ParameterNaming.PASSWORD + "\" (and optionally \"" + ParameterNaming.ALGORITHM + "\" and \"" + ParameterNaming.KEY_OBTENTION_ITERATIONS + "\") " + "must be specified"); } } private synchronized void checkInitialization() { if (!this.initialized) { if (this.useEncryptorName) { final HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); final PBEByteEncryptor pbeEncryptor = registry.getPBEByteEncryptor(this.encryptorName); if (pbeEncryptor == null) { throw new EncryptionInitializationException( "No big integer encryptor registered for hibernate " + "with name \"" + this.encryptorName + "\""); } this.encryptor = pbeEncryptor; } else { final StandardPBEByteEncryptor newEncryptor = new StandardPBEByteEncryptor(); newEncryptor.setPassword(this.password); if (this.algorithm != null) { newEncryptor.setAlgorithm(this.algorithm); } if (this.keyObtentionIterations != null) { newEncryptor.setKeyObtentionIterations( this.keyObtentionIterations.intValue()); } newEncryptor.initialize(); this.encryptor = newEncryptor; } this.initialized = true; } } } EncryptedBooleanAsStringType.java000066400000000000000000000072401360667575700360370ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Boolean values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="active" column="ACTIVE" type="encryptedBooleanAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedBooleanAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return Boolean.valueOf(string); } public Class returnedClass() { return Boolean.class; } } EncryptedByteAsStringType.java000066400000000000000000000071771360667575700353740ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Byte values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedByteAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedByteAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Byte(string); } public Class returnedClass() { return Byte.class; } } EncryptedCalendarAsStringType.java000066400000000000000000000131711360667575700361710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.util.Calendar; import java.util.Properties; import java.util.TimeZone; import org.jasypt.commons.CommonUtils; /** *

* A Hibernate UserType implementation which allows * encryption of Calendar values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* The boolean storeTimeZone parameter allows the Calendar to be * re-created with the same TimeZone that it was created. This is an * optional parameter, and its default value is FALSE. *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *      <param name="storeTimeZone">true</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedCalendarAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedCalendarAsStringType extends AbstractEncryptedAsStringType{ private Boolean storeTimeZone = Boolean.FALSE; /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final String[] stringTokens = CommonUtils.split(string); TimeZone tz = null; final long timeMillis = Long.valueOf(stringTokens[0]).longValue(); if (this.storeTimeZone.booleanValue()) { tz = TimeZone.getTimeZone(stringTokens[1]); } else { tz = TimeZone.getDefault(); } final Calendar cal = Calendar.getInstance(); cal.setTimeZone(tz); cal.setTimeInMillis(timeMillis); return cal; } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final StringBuffer strBuff = new StringBuffer(); final long timeMillis = ((Calendar) object).getTimeInMillis(); strBuff.append((new Long(timeMillis)).toString()); if (this.storeTimeZone.booleanValue()) { strBuff.append(" "); strBuff.append(((Calendar) object).getTimeZone().getID()); } return strBuff.toString(); } public synchronized void setParameterValues(final Properties parameters) { super.setParameterValues(parameters); final String paramStoreTimeZone = parameters.getProperty(ParameterNaming.STORE_TIME_ZONE); if ((paramStoreTimeZone != null) && (!paramStoreTimeZone.trim().equals(""))) { this.storeTimeZone = CommonUtils.getStandardBooleanValue(paramStoreTimeZone); } } public Class returnedClass() { return Calendar.class; } } EncryptedDateAsStringType.java000066400000000000000000000077731360667575700353500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; import java.util.Date; /** *

* A Hibernate UserType implementation which allows * encryption of Date values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="birth" column="BIRTH" type="encryptedDateAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedDateAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { final long timeMillis = Long.valueOf(string).longValue(); return new Date(timeMillis); } /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToString(java.lang.Object) */ protected String convertToString(final Object object) { final long timeMillis = ((Date) object).getTime(); return String.valueOf(timeMillis); } public Class returnedClass() { return Date.class; } } EncryptedDoubleAsStringType.java000066400000000000000000000072231360667575700356730ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Double values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedDoubleAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedDoubleAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Double(string); } public Class returnedClass() { return Double.class; } } EncryptedFloatAsStringType.java000066400000000000000000000072121360667575700355240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Float values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedFloatAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedFloatAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Float(string); } public Class returnedClass() { return Float.class; } } EncryptedIntegerAsStringType.java000066400000000000000000000072401360667575700360550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Integer values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedIntegerAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedIntegerAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Integer(string); } public Class returnedClass() { return Integer.class; } } EncryptedLongAsStringType.java000066400000000000000000000072021360667575700353550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Long values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedLongAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedLongAsStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Long(string); } public Class returnedClass() { return Long.class; } } EncryptedShortAsStringType.java000066400000000000000000000072211360667575700355560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows * encryption of Short values into String (VARCHAR) database fields * during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="salary" column="SALARY" type="encryptedShortAsString" />
 *      ...
 *    <class>
 *    ...
 *  <hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedShortAsStringType extends AbstractEncryptedAsStringType { /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String string) { return new Short(string); } public Class returnedClass() { return Short.class; } } EncryptedStringType.java000066400000000000000000000071111360667575700342500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* A Hibernate UserType implementation which allows transparent * encryption of String values during persistence of entities. *

*

* This class is intended only for declarative use from a Hibernate mapping * file. Do not use it directly from your .java files (although * of course you can use it when mapping entities using annotations). *

*

* To use this Hibernate type in one of your Hibernate mappings, you can * add it like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="encryptorRegisteredName">myHibernateStringEncryptor</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* ...where a HibernatePBEStringEncryptor object * should have been previously registered to be used * from Hibernate with name myHibernateStringEncryptor (see * {@link HibernatePBEStringEncryptor} and {@link HibernatePBEEncryptorRegistry}). *

*

* Or, if you prefer to avoid registration of encryptors, you can configure * your encryptor directly in the mapping file (although not recommended), * like this: *

*

*

 *  <hibernate-mapping package="myapp">
 *    ...
 *    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
 *      <param name="algorithm">PBEWithMD5AndTripleDES</param>
 *      <param name="password">XXXXX</param>
 *      <param name="keyObtentionIterations">1000</param>
 *    </typedef>
 *    ...
 *    <class name="UserData" table="USER_DATA">
 *      ...
 *      <property name="address" column="ADDRESS" type="encryptedString" />
 *      ...
 *    </class>
 *    ...
 *  </hibernate-mapping>
 * 
*

*

* To learn more about usage of user-defined types, please refer to the * Hibernate Reference * Documentation. *

* * * @since 1.9.0 * * @author Chus Picos * */ public final class EncryptedStringType extends AbstractEncryptedAsStringType{ /** * @see org.jasypt.hibernate.type.AbstractEncryptedAsStringType#convertToObject(java.lang.String) */ protected Object convertToObject(final String stringValue) { return stringValue; } public Class returnedClass() { return String.class; } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/main/java/org/jasypt/hibernate5/type/ParameterNaming.java000066400000000000000000000063111360667575700334140ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.type; /** *

* Constant names of the parameters that can be used by a jasypt type's * typedef declaration in a Hibernate mapping. *

* * @since 1.9.0 * * @author Chus Picos * */ public final class ParameterNaming { /** *

* The registered name of an encryptor previously registered at the * {@link org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry}. *

*

* Value = encryptorRegisteredName *

*/ public static final String ENCRYPTOR_NAME = "encryptorRegisteredName"; /** *

* The encryption algorithm. *

*

* Value = algorithm *

*/ public static final String ALGORITHM = "algorithm"; /** *

* The name of the JCE security provider we want to get the algorithm from * (if it is no the default one. *

*

* Value = providerName *

*/ public static final String PROVIDER_NAME = "providerName"; /** *

* The encryption password. *

*

* Value = password *

*/ public static final String PASSWORD = "password"; /** *

* The number of hashing iterations to be applied for obtaining the * encryption key. *

*

* Value = keyObtentionIterations *

*/ public static final String KEY_OBTENTION_ITERATIONS = "keyObtentionIterations"; /** *

* The type of String output ("base64" (default), "hexadecimal") to be * generated. *

*

* Value = stringOutputType *

*/ public static final String STRING_OUTPUT_TYPE = "stringOutputType"; /** *

* The scale (numbers after the decimal point) to be used when storing * decimal numbers. *

*

* Value = decimalScale *

*/ public static final String DECIMAL_SCALE = "decimalScale"; /** *

* Whether the calendar time zone should be stored with the date or not. *

*

* Value = storeTimeZone *

*/ public static final String STORE_TIME_ZONE = "storeTimeZone"; private ParameterNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/000077500000000000000000000000001360667575700215005ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/000077500000000000000000000000001360667575700224215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/000077500000000000000000000000001360667575700232105ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/000077500000000000000000000000001360667575700245225ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/000077500000000000000000000000001360667575700265505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/model/000077500000000000000000000000001360667575700276505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/model/user/000077500000000000000000000000001360667575700306265ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/model/user/User.hbm.xml000066400000000000000000000042101360667575700330300ustar00rootroot00000000000000 hibernateStringEncryptor hibernateStringEncryptor hibernateByteEncryptor hibernateBigIntegerEncryptor hibernateBigDecimalEncryptor 2 jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/model/user/User.java000066400000000000000000000056141360667575700324150ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.model.user; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Calendar; import org.apache.commons.lang.builder.ToStringBuilder; /** * * @author Chus Picos * */ public class User { private String name; private String login; private String password; private Calendar birthdate; private byte[] document; private BigInteger code; private BigDecimal code2; public User(String name, String login, String password, Calendar birthdate, byte[] document, BigInteger code, BigDecimal code2) { super(); this.name = name; this.login = login; this.password = password; this.birthdate = birthdate; this.document = document; this.code = code; this.code2 = code2; } public User() { super(); } public String toString() { return new ToStringBuilder(this).append("name", this.name) .append("login", this.login).append("password", this.password) .append("birthdate", this.birthdate) .append("document", this.document) .append("code", this.code).append("code 2", this.code2) .toString(); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getLogin() { return this.login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Calendar getBirthdate() { return this.birthdate; } public void setBirthdate(Calendar birthdate) { this.birthdate = birthdate; } public byte[] getDocument() { return this.document; } public void setDocument(byte[] document) { this.document = document; } public BigInteger getCode() { return this.code; } public void setCode(BigInteger code) { this.code = code; } public BigDecimal getCode2() { return this.code2; } public void setCode2(BigDecimal code2) { this.code2 = code2; } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/test/000077500000000000000000000000001360667575700275275ustar00rootroot00000000000000TestHibernateTypes.java000066400000000000000000000167351360667575700341150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/java/org/jasypt/hibernate5/test/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.hibernate5.test; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Connection; import java.sql.SQLException; import java.util.Calendar; import java.util.Random; import org.apache.commons.lang.RandomStringUtils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.jdbc.Work; import org.hibernate.testing.ServiceRegistryBuilder; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.hibernate5.encryptor.HibernatePBEEncryptorRegistry; import org.jasypt.hibernate5.model.user.User; import junit.framework.TestCase; /** * * @author Chus Picos * */ public class TestHibernateTypes extends TestCase { private static Configuration hbConf; private static SessionFactory sessionFactory; private static String userLogin; private static String userName; private static String userPassword; private static Calendar userBirthdate; private static byte[] userDocument; private static BigInteger userCode; private static BigDecimal userCode2; static Session session; public TestHibernateTypes() { super(); } public TestHibernateTypes(String name) { super(name); } public void testCreateAndReadUser() throws Exception { initialize(); createUser(); readUser(); finish(); } private void initialize() { registerEncryptors(); // Configure Hibernate and open session Configuration cfg = new Configuration(); cfg.setProperty(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect"); cfg.setProperty(Environment.URL, "jdbc:hsqldb:mem:jasypttestdb"); cfg.setProperty(Environment.DRIVER, "org.hsqldb.jdbcDriver"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.POOL_SIZE, "10"); StandardServiceRegistry serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()); hbConf = new Configuration(); sessionFactory = hbConf .addClass(User.class) .setProperty(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect") .setProperty(Environment.URL, "jdbc:hsqldb:mem:jasypttestdb") .setProperty(Environment.DRIVER, "org.hsqldb.jdbcDriver") .setProperty(Environment.USER, "sa") .setProperty(Environment.PASS, "") .setProperty(Environment.POOL_SIZE, "10") .buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); initDB(); generateData(); } private void registerEncryptors() { StandardPBEStringEncryptor stringEncryptor = new StandardPBEStringEncryptor(); stringEncryptor.setAlgorithm("PBEWithMD5AndDES"); stringEncryptor.setPassword("jasypt-hibernate5-test"); StandardPBEByteEncryptor byteEncryptor = new StandardPBEByteEncryptor(); byteEncryptor.setAlgorithm("PBEWithMD5AndDES"); byteEncryptor.setPassword("jasypt-hibernate5-test"); StandardPBEBigIntegerEncryptor bigIntegerEncryptor = new StandardPBEBigIntegerEncryptor(); bigIntegerEncryptor.setAlgorithm("PBEWithMD5AndDES"); bigIntegerEncryptor.setPassword("jasypt-hibernate5-test"); StandardPBEBigDecimalEncryptor bigDecimalEncryptor = new StandardPBEBigDecimalEncryptor(); bigDecimalEncryptor.setAlgorithm("PBEWithMD5AndDES"); bigDecimalEncryptor.setPassword("jasypt-hibernate5-test"); HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance(); registry.registerPBEStringEncryptor("hibernateStringEncryptor", stringEncryptor); registry.registerPBEByteEncryptor("hibernateByteEncryptor", byteEncryptor); registry.registerPBEBigIntegerEncryptor("hibernateBigIntegerEncryptor", bigIntegerEncryptor); registry.registerPBEBigDecimalEncryptor("hibernateBigDecimalEncryptor", bigDecimalEncryptor); } /** * Create db structure */ private void initDB() { Transaction transaction = session.beginTransaction(); session.doWork(new Work() { public void execute(Connection connection) throws SQLException { connection.createStatement().execute( "CREATE MEMORY TABLE PUBLIC.USER(" + "NAME VARCHAR(100)," + "LOGIN VARCHAR(100) PRIMARY KEY," + "PASSWORD VARCHAR(100)," + "BIRTHDATE VARCHAR(100)," + "DOCUMENT BLOB," + "CODE NUMERIC, " + "CODE2 NUMERIC);"); } }); transaction.commit(); } /** * Generate data to test with */ private void generateData() { userLogin = RandomStringUtils.randomAlphabetic(5); userName = RandomStringUtils.randomAlphabetic(10); userPassword = RandomStringUtils.randomAlphanumeric(15); userBirthdate = Calendar.getInstance(); try { userDocument = RandomStringUtils.randomAlphabetic(100).getBytes( "ISO-8859-1"); } catch (UnsupportedEncodingException e) { assertTrue(false); } userCode = new BigInteger(256, new Random()); userCode2 = new BigDecimal(Math.random()); } private void finish() { session.close(); } private void createUser() throws Exception { User user = new User(userName, userLogin, userPassword, userBirthdate, userDocument, userCode, userCode2); Transaction transaction = session.beginTransaction(); session.saveOrUpdate(user); System.out.println("User stored: " + user); transaction.commit(); assertTrue(true); } private void readUser() throws Exception { Transaction transaction = session.beginTransaction(); User user = (User) session.load(User.class, userLogin); System.out.println("User read: " + user); transaction.commit(); assertEquals(user.getLogin(), userLogin); assertEquals(user.getName(), userName); assertEquals(user.getPassword(), userPassword); assertEquals(user.getBirthdate(), userBirthdate); assertEquals(user.getDocument(), userDocument); assertEquals(user.getCode(), userCode); assertEquals(user.getCode2(), userCode2); } } jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/resources/000077500000000000000000000000001360667575700235125ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-hibernate5/src/test/resources/log4j.properties000066400000000000000000000004011360667575700266420ustar00rootroot00000000000000log4j.rootLogger = WARN, stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p [%c{1}] (%F:%L) - %m%n jasypt-jasypt-1.9.3/jasypt-spring2/000077500000000000000000000000001360667575700172705ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/.gitignore000066400000000000000000000000721360667575700212570ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring2/BUILD.txt000066400000000000000000000014501360667575700206700ustar00rootroot00000000000000 Building JASYPT-SPRING2 ----------------------- To build JASYPT-SPRING2 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRING2 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-spring2-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-spring2/{version}/jasypt-spring2-{version}.jar Generating Javadoc for JASYPT-SPRING2 ------------------------------------- If you wish to generate the javadoc for JASYPT-SPRING2, execute this from the JASYPT-SPRING2 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-spring2/ChangeLog.txt000066400000000000000000000006631360667575700216650ustar00rootroot000000000000001.9.3 ===== - Deprecated in 1.9.3. This module will be removed in 2.0.0. 1.9.2 ===== - Fixed EncryptablePreferencesPlaceholderConfigurer not applying value decryption when needed. 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-spring2 package from previous monolithic jasypt module. - Renamed org.jasypt.spring package as org.jasypt.spring2, and deprecated the classes in the old package. - Created additional tests jasypt-jasypt-1.9.3/jasypt-spring2/LICENSE.txt000066400000000000000000000261361360667575700211230ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-spring2/NOTICE.txt000066400000000000000000000072671360667575700210260ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-spring2/README.txt000066400000000000000000000006111360667575700207640ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-spring2/RELEASING.txt000066400000000000000000000023061360667575700213430ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-spring2/USAGE.txt000066400000000000000000000011731360667575700206770ustar00rootroot00000000000000 Using JASYPT-SPRING2 from Maven 2 --------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-spring2 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-spring2/pom.xml000066400000000000000000000173741360667575700206210ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring2 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.1 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework spring-core 2.5 provided true org.springframework spring-beans 2.5 provided true org.springframework spring-web 2.5 provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-spring2/src/000077500000000000000000000000001360667575700200575ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/000077500000000000000000000000001360667575700210035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/000077500000000000000000000000001360667575700217245ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/000077500000000000000000000000001360667575700225135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/000077500000000000000000000000001360667575700240255ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/000077500000000000000000000000001360667575700253275ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/properties/000077500000000000000000000000001360667575700275235ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000074301360667575700411340ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.7 * * @author Daniel Fernández * * @deprecated Package renamed as org.jasypt.spring2.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000075371360667575700400640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.4 * * @author Marcos Muíño García * * @deprecated Package renamed as org.jasypt.spring2.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000103231360667575700405120ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.4 * * @author Marcos Muíño García * @author Carlos Fernández * * @deprecated Package renamed as org.jasypt.spring2.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptableServletContextPropertyPlaceholderConfigurer.java000066400000000000000000000110131360667575700434210ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt servlet context parameter values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

<param-value>ENC(!"DGAS24FaIO$)</param-value>
*

* * @since 1.7 * * @author Daniel Fernández * * @deprecated Package renamed as org.jasypt.spring2.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptableServletContextPropertyPlaceholderConfigurer extends ServletContextPropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * Spring's ServletContextPropertyPlaceholderConfigurer never creates a complete * map of properties, and so never really applies the "convertPropertyValue" method * to them. Instead it gets properties on the fly and returns them without conversion * (as of Spring 3.0.5). * * This fix makes sure that variables are decrypted before being returned. */ protected String resolvePlaceholder(final String placeholder, final Properties props) { return convertPropertyValue(super.resolvePlaceholder(placeholder, props)); } } jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/000077500000000000000000000000001360667575700254115ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/properties/000077500000000000000000000000001360667575700276055ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000113261360667575700412150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.properties; import java.util.Properties; import java.util.prefs.Preferences; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.7) * * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.util.Properties) */ protected String resolvePlaceholder(final String placeholder, final Properties props) { final String result = super.resolvePlaceholder(placeholder, props); return convertPropertyValue(result); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.lang.String, java.util.prefs.Preferences) */ protected String resolvePlaceholder( final String path, final String key, final Preferences preferences) { final String result = super.resolvePlaceholder(path, key, preferences); return convertPropertyValue(result); } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000075411360667575700401410ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.4) * * @author Marcos Muíño García * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000103251360667575700405760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.4) * * @author Marcos Muíño García * @author Carlos Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptableServletContextPropertyPlaceholderConfigurer.java000066400000000000000000000110151360667575700435050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/main/java/org/jasypt/spring2/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.properties; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt servlet context parameter values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

<param-value>ENC(!"DGAS24FaIO$)</param-value>
*

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.7) * * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class EncryptableServletContextPropertyPlaceholderConfigurer extends ServletContextPropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * Spring's ServletContextPropertyPlaceholderConfigurer never creates a complete * map of properties, and so never really applies the "convertPropertyValue" method * to them. Instead it gets properties on the fly and returns them without conversion * (as of Spring 3.0.5). * * This fix makes sure that variables are decrypted before being returned. */ protected String resolvePlaceholder(final String placeholder, final Properties props) { return convertPropertyValue(super.resolvePlaceholder(placeholder, props)); } } jasypt-jasypt-1.9.3/jasypt-spring2/src/test/000077500000000000000000000000001360667575700210365ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/000077500000000000000000000000001360667575700217575ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/000077500000000000000000000000001360667575700225465ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/000077500000000000000000000000001360667575700240605ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/000077500000000000000000000000001360667575700254445ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/configuration/000077500000000000000000000000001360667575700303135ustar00rootroot00000000000000ConfigurationProperties.java000066400000000000000000000034311360667575700357640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/configuration/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.configuration; /** * * @author Soraya Sánchez * */ public class ConfigurationProperties { private String location; private String locatinPlainValue; private String locationEncryptedValue; public ConfigurationProperties() { super(); } public String getLocation() { return this.location; } public void setLocation(String location) { this.location = location; } public String getLocatinPlainValue() { return this.locatinPlainValue; } public void setLocationPlainValue(String locatinPlainValue) { this.locatinPlainValue = locatinPlainValue; } public String getLocationEncryptedValue() { return this.locationEncryptedValue; } public void setLocationEncryptedValue(String locatinEncryptedValue) { this.locationEncryptedValue = locatinEncryptedValue; } } jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/properties/000077500000000000000000000000001360667575700276405ustar00rootroot00000000000000EncryptablePropertyPlaceholderConfigurerTest.java000066400000000000000000000157531360667575700415030ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.properties; import junit.framework.TestCase; import java.util.HashMap; import java.util.Map; import org.jasypt.encryption.StringEncryptor; import org.jasypt.util.text.TextEncryptor; /* * ==Test resolveSystemProperty for encrypted env var== * * I don't have a great way to test the decryption of encrypted env var without requiring the test harness (surefire, IDE etc) * to have specified an encrypted environment variable. Here are a few options * - reflection hack to change the underlying system env map - * http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java. THis is what spring does to * test the propertyplaceholderconfigurer: * https://src.springframework.org/svn/spring-framework/trunk/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java * - extract the call to super.resolveSystemProperty(key) in resolveSystemProperty to a protected method and the test * will use a testspecifc subclass (http://xunitpatterns.com/Test-Specific%20Subclass.html) that overrides that method. * * However, i really don't think it is that big of a deal. The functionality responsible for getting system/env values * is defined in the super. All this class does is check to see if they have the encryption delimiters. I am pretty sure * I already went overboard on the test - ~100 lines of test for 3 lines of production code. * * User: carlos fernandez * Date: 6/28/11 * Time: 10:38 PM */ public class EncryptablePropertyPlaceholderConfigurerTest extends TestCase { //duplicated prefix suffix values in PropertyValueEncryptionUtils because PVEU constants are private private static final String ENCRYPTED_VALUE_PREFIX = "ENC("; private static final String ENCRYPTED_VALUE_SUFFIX = ")"; private String expectedDecryptedValue; private String encryptedValue; private String encryptedValueWithDelimiters; private String encryptedSysPropKey; private String unencryptedSysPropKey; private String unencryptedValue; public void setUp() { encryptedSysPropKey = "thisIsAnEncryptedSysPropertyKey"; encryptedValue = "encryptedString"; encryptedValueWithDelimiters = ENCRYPTED_VALUE_PREFIX + this.encryptedValue + ENCRYPTED_VALUE_SUFFIX; expectedDecryptedValue = "clearText"; System.setProperty(encryptedSysPropKey, encryptedValueWithDelimiters); unencryptedSysPropKey = "thisIsAnUNEncryptedSysPropertyKey"; unencryptedValue = "thisIsARegularString"; System.setProperty(unencryptedSysPropKey, unencryptedValue); } public void testConvertPropertyValueNotEncrypted() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, eppc.convertPropertyValue(unencryptedValue)); } public void testConvertPropertyValueDecryptWithStringEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testConvertPropertyValueDecryptWithTextEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testResolveSystemPropertyNullSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertNull(ppc.resolveSystemProperty("foofoofoo")); } public void testResolveSystemPropertyEncryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, ppc.resolveSystemProperty(encryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, ppc.resolveSystemProperty(unencryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedEnvVar() throws Exception { //the expectation is that the system has the HOME env var String unencryptedEnvVarKey = "HOME";//this is expected to exist on windows and unix systems String unencryptedEnvVarValue = System.getenv(unencryptedEnvVarKey); //lets make sure the env variable is set & is not null assertNotNull("no home env variable found", unencryptedEnvVarValue); EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); //allow ppc can check env vars ppc.setSearchSystemEnvironment(true); assertEquals(unencryptedEnvVarValue, ppc.resolveSystemProperty(unencryptedEnvVarKey)); } private EncryptablePropertyPlaceholderConfigurer createPPCWithTextEncryptor() { StubTextEncryptor textEncryptor = new StubTextEncryptor(); textEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(textEncryptor); } private EncryptablePropertyPlaceholderConfigurer createPPCWithStringEncryptor() { StubStringEncryptor stringEncryptor = new StubStringEncryptor(); stringEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(stringEncryptor); } abstract class StubEncryptor { private Map decryptMap = new HashMap(); public String decrypt(String encryptedMessage) { return (String)this.decryptMap.get(encryptedMessage); } public String encrypt(String message) { throw new UnsupportedOperationException(); } public void addDecryption(String encrypted, String expectedDecryption) { this.decryptMap.put(encrypted, expectedDecryption); } } class StubStringEncryptor extends StubEncryptor implements StringEncryptor{} class StubTextEncryptor extends StubEncryptor implements TextEncryptor{} } jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/test/000077500000000000000000000000001360667575700264235ustar00rootroot00000000000000TestSpringConfiguration.java000066400000000000000000000045511360667575700340460ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/java/org/jasypt/spring2/test/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring2.test; import junit.framework.TestCase; import org.jasypt.encryption.StringEncryptor; import org.jasypt.spring2.configuration.ConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * * @author Soraya Sánchez * */ public class TestSpringConfiguration extends TestCase { private final static String CONFIGURATION_ENCRYPTOR_BEAN_NAME = "configurationEncryptor"; private final static String CONFIGURATION_PROPERTIES_BEAN_NAME = "configurationProperties"; private static ApplicationContext ctx; protected void setUp() throws Exception { super.setUp(); initSpring(); } public static void initSpring() { ctx = new ClassPathXmlApplicationContext(new String[] {"spring.xml"}); } public void testEncryptedProperties() throws Exception { ConfigurationProperties configurationProperties = (ConfigurationProperties) ctx.getBean(CONFIGURATION_PROPERTIES_BEAN_NAME); StringEncryptor stringEncryptor = (StringEncryptor) ctx.getBean(CONFIGURATION_ENCRYPTOR_BEAN_NAME); assertEquals(configurationProperties.getLocation(), configurationProperties.getLocatinPlainValue()); assertEquals(stringEncryptor.decrypt(configurationProperties.getLocationEncryptedValue()), configurationProperties.getLocation()); } } jasypt-jasypt-1.9.3/jasypt-spring2/src/test/resources/000077500000000000000000000000001360667575700230505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring2/src/test/resources/props.properties000066400000000000000000000001731360667575700263320ustar00rootroot00000000000000location=ENC(v0z0uGQRucwfBau0e+gB6A\=\=) location.plain.value=Spain location.encrypted.value=v0z0uGQRucwfBau0e+gB6A\=\= jasypt-jasypt-1.9.3/jasypt-spring2/src/test/resources/spring.xml000066400000000000000000000052111360667575700250730ustar00rootroot00000000000000 jasypt-jasypt-1.9.3/jasypt-spring3-testapp/000077500000000000000000000000001360667575700207475ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/.gitignore000066400000000000000000000000721360667575700227360ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring3-testapp/pom.xml000066400000000000000000000216331360667575700222710ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring3-testapp war 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone src/main/resources src/main/java **/*.properties **/*.xml **/*.html org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 org.apache.maven.plugins maven-resources-plugin 2.5 ISO-8859-1 org.jasypt jasypt 1.9.3 compile org.jasypt jasypt-spring3 1.9.3 compile javax.servlet servlet-api 2.5 provided org.springframework spring-core 3.0.5.RELEASE compile org.springframework spring-context 3.0.5.RELEASE compile org.springframework spring-beans 3.0.5.RELEASE compile org.springframework spring-aop 3.0.5.RELEASE compile org.springframework spring-aspects 3.0.5.RELEASE compile org.springframework spring-expression 3.0.5.RELEASE compile org.springframework spring-web 3.0.5.RELEASE compile org.springframework spring-webmvc 3.0.5.RELEASE compile javax.validation validation-api 1.0.0.GA compile org.hibernate hibernate-validator-annotation-processor 4.1.0.Final org.slf4j slf4j-api 1.6.1 compile org.slf4j slf4j-log4j12 1.6.1 compile log4j log4j 1.2.15 compile com.sun.jdmk jmxtools com.sun.jmx jmxri javax.jms jms javax.servlet jsp-api 2.0 provided javax.servlet jstl 1.1.2 compile taglibs standard 1.1.2 compile jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/000077500000000000000000000000001360667575700215365ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/000077500000000000000000000000001360667575700224625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/000077500000000000000000000000001360667575700234035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/000077500000000000000000000000001360667575700241725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/jasypt/000077500000000000000000000000001360667575700255045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/jasypt/spring3testapp/000077500000000000000000000000001360667575700304725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/jasypt/spring3testapp/web/000077500000000000000000000000001360667575700312475ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/jasypt/spring3testapp/web/controller/000077500000000000000000000000001360667575700334325ustar00rootroot00000000000000Index.java000066400000000000000000000130621360667575700352670ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/java/org/jasypt/spring3testapp/web/controller/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3testapp.web.controller; import java.util.Properties; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.StringDigester; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Index { @Autowired private PBEByteEncryptor enc1; @Autowired private PBEBigDecimalEncryptor enc3; @Autowired private PBEBigIntegerEncryptor enc4; @Autowired private PBEStringEncryptor encAES; @Autowired private BasicTextEncryptor bte; @Autowired private StrongTextEncryptor ste; @Autowired private StringDigester sd; @Autowired private ByteDigester bd; @Autowired private PasswordEncryptor bpe; @Autowired @Qualifier("eprop1") private Properties eprop1; @Autowired private ApplicationContext appCtx; @Autowired @Qualifier("eprop2") private Properties eprop2; @Value("${city.name}") private String cityName; @Value("${country.name}") private String countryName; public Index() { super(); } @RequestMapping({"/"}) public String show(final ModelMap model) { final byte[] mba = "Hello!".getBytes(); final byte[] encMba = this.enc1.encrypt(mba); model.addAttribute("encMba", new String(encMba) + " | " + enc1.getClass().getName()); final StandardPBEStringEncryptor enctest = new StandardPBEStringEncryptor(); enctest.setPassword("jasypt"); enctest.setAlgorithm("PBEWithMD5AndTripleDES"); enctest.setStringOutputType("hexa"); enctest.setKeyObtentionIterations(20); System.out.println("BigDecimal: " + enc3.getClass().getName()); System.out.println("BigInteger: " + enc4.getClass().getName()); String bteE = bte.encrypt("hello!"); System.out.println("Basic encryptor: " + bte.getClass().getName() + bteE + " -> " + bte.decrypt(bteE)); String steE = ste.encrypt("hello!"); System.out.println("Strong encryptor: " + ste.getClass().getName() + steE + " -> " + ste.decrypt(steE)); String encAESe = encAES.encrypt("hello!"); System.out.println("AES: " + encAES.getClass().getName() + encAESe + " -> " + encAES.decrypt(encAESe)); model.addAttribute("encAES", new String(encAESe) + " | " + encAES.getClass().getName()); System.out.println(sd.digest("myPassword") + " | " + sd.getClass().getName()); System.out.println(new String(bd.digest(mba)) + " | " + bd.getClass().getName()); final String ep = bpe.encryptPassword("HELLO!!"); System.out.println(ep + " | " + bpe.getClass().getName()); final ConfigurablePasswordEncryptor configurablePasswordEncryptor = new ConfigurablePasswordEncryptor(); configurablePasswordEncryptor.setAlgorithm("SHA-1"); configurablePasswordEncryptor.setStringOutputType("0x"); System.out.println(configurablePasswordEncryptor.checkPassword("HELLO!!", ep)); System.out.println(this.eprop1); System.out.println(this.eprop2); System.out.println("----------"); System.out.println(this.eprop1.getProperty("prop1")); System.out.println(this.eprop1.getProperty("prop2")); System.out.println("Existing digester: " + System.identityHashCode(this.sd)); StringDigester stex = (StringDigester) appCtx.getBean("sd1"); System.out.println("First digester: " + System.identityHashCode(stex)); stex = (StringDigester) appCtx.getBean("sd1"); System.out.println("Second digester: " + System.identityHashCode(stex)); System.out.println("City name: " + this.cityName); System.out.println("Country name: " + this.countryName); return "index"; } } jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/resources/000077500000000000000000000000001360667575700244745ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/resources/log4j.properties000066400000000000000000000004061360667575700276310ustar00rootroot00000000000000log4j.rootLogger = WARN, stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p [%c{1}] (%F:%L) - %m%n jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/resources/some.properties000066400000000000000000000001121360667575700275470ustar00rootroot00000000000000country.name=ENC(zl94ORjq8JUSN/c5xGgVxomrMd5bf9K4) city.name=Penguin City jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/000077500000000000000000000000001360667575700237405ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/META-INF/000077500000000000000000000000001360667575700251005ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/META-INF/MANIFEST.MF000066400000000000000000000000471360667575700265330ustar00rootroot00000000000000Manifest-Version: 1.0 Class-Path: jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/WEB-INF/000077500000000000000000000000001360667575700247675ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/WEB-INF/spring-servlet.xml000066400000000000000000000113271360667575700305010ustar00rootroot00000000000000 something ENC(JhuIj9BJvw7nEix0n4oM/VG0kgOTK51p4E1vzEWn65Nc7y8EfLomhCStYBNSyR4J) something-two jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/WEB-INF/templates/000077500000000000000000000000001360667575700267655ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/WEB-INF/templates/index.jsp000066400000000000000000000013521360667575700306130ustar00rootroot00000000000000<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %><%@ taglib prefix="s" uri="http://www.springframework.org/tags" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Jasypt Spring3 Test Application

This is a JSP

jasypt-jasypt-1.9.3/jasypt-spring3-testapp/src/main/webapp/WEB-INF/web.xml000066400000000000000000000015731360667575700262740ustar00rootroot00000000000000 jasypt-spring3-testapp 60 spring org.springframework.web.servlet.DispatcherServlet 1 spring / index jasypt-jasypt-1.9.3/jasypt-spring3/000077500000000000000000000000001360667575700172715ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/.gitignore000066400000000000000000000000721360667575700212600ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring3/BUILD.txt000066400000000000000000000014501360667575700206710ustar00rootroot00000000000000 Building JASYPT-SPRING3 ----------------------- To build JASYPT-SPRING3 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRING3 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-spring3-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-spring3/{version}/jasypt-spring3-{version}.jar Generating Javadoc for JASYPT-SPRING3 ------------------------------------- If you wish to generate the javadoc for JASYPT-SPRING3, execute this from the JASYPT-SPRING3 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-spring3/ChangeLog.txt000066400000000000000000000036711360667575700216700ustar00rootroot000000000000001.9.3 ===== - Fixed #32: encryption works but decryption does not, Java 8 (JCE jars installed). Added support for initialization vectors needed for AES encryption and decryption since Java 8. 1.9.2 ===== - Fixed EncryptablePreferencesPlaceholderConfigurer not applying value decryption when needed. 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-spring3 package from previous monolithic jasypt module. - Renamed org.jasypt.spring package as org.jasypt.spring3, and deprecated the classes in the old package. - Created the "encryption" XML namespace, containing tags for: * Encryptors * PBE encryptor config objects: * PBE byte encryptor objects: * PBE string encryptor objects: * PBE big decimal encryptor objects: * PBE big integer encryptor objects: * Digesters * Digester config objects: * Digester byte digester objects: * Digester string digester objects: * Util encryptors/digesters * Basic text encryptor objects: * Strong text encryptor objects: * Basic password encryptor objects: * Strong password encryptor objects: * Configurable password encryptor objects: * Encryptable properties * Encryptable properties objects (java.util.Properties): * Encryptable property placeholder configurer: * Encryptable property override configurer: jasypt-jasypt-1.9.3/jasypt-spring3/LICENSE.txt000066400000000000000000000261361360667575700211240ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-spring3/NOTICE.txt000066400000000000000000000072671360667575700210270ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-spring3/README.txt000066400000000000000000000006111360667575700207650ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-spring3/RELEASING.txt000066400000000000000000000023061360667575700213440ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-spring3/USAGE.txt000066400000000000000000000011731360667575700207000ustar00rootroot00000000000000 Using JASYPT-SPRING3 from Maven 2 --------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-spring3 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-spring3/pom.xml000066400000000000000000000206621360667575700206140ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring3 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone src/main/java **/*.xsd src/main/resources . META-INF LICENSE.txt NOTICE.txt src/main/metainf META-INF spring.handlers spring.schemas src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework spring-core 3.0.0.RELEASE provided true org.springframework spring-beans 3.0.0.RELEASE provided true org.springframework spring-web 3.0.0.RELEASE provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-spring3/src/000077500000000000000000000000001360667575700200605ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/000077500000000000000000000000001360667575700210045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/000077500000000000000000000000001360667575700217255ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/000077500000000000000000000000001360667575700225145ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/000077500000000000000000000000001360667575700240265ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/000077500000000000000000000000001360667575700253305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/properties/000077500000000000000000000000001360667575700275245ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000074301360667575700411350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.7 * * @author Daniel Fernández * * @deprecated Package renamed as org.jasypt.spring3.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000075371360667575700400650ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.4 * * @author Marcos Muíño García * * @deprecated Package renamed as org.jasypt.spring3.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000103231360667575700405130ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.4 * * @author Marcos Muíño García * @author Carlos Fernández * * @deprecated Package renamed as org.jasypt.spring3.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptableServletContextPropertyPlaceholderConfigurer.java000066400000000000000000000110131360667575700434220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.properties; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt servlet context parameter values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

<param-value>ENC(!"DGAS24FaIO$)</param-value>
*

* * @since 1.7 * * @author Daniel Fernández * * @deprecated Package renamed as org.jasypt.spring3.properties. Classes in * this package will be removed in 1.11. * */ public final class EncryptableServletContextPropertyPlaceholderConfigurer extends ServletContextPropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * Spring's ServletContextPropertyPlaceholderConfigurer never creates a complete * map of properties, and so never really applies the "convertPropertyValue" method * to them. Instead it gets properties on the fly and returns them without conversion * (as of Spring 3.0.5). * * This fix makes sure that variables are decrypted before being returned. */ protected String resolvePlaceholder(final String placeholder, final Properties props) { return convertPropertyValue(super.resolvePlaceholder(placeholder, props)); } } jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/000077500000000000000000000000001360667575700254135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/properties/000077500000000000000000000000001360667575700276075ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000112641360667575700412200ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.properties; import java.util.Properties; import java.util.prefs.Preferences; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.7) * * @author Daniel Fernández * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.util.Properties) */ @Override protected String resolvePlaceholder(final String placeholder, final Properties props) { final String result = super.resolvePlaceholder(placeholder, props); return convertPropertyValue(result); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.lang.String, java.util.prefs.Preferences) */ @Override protected String resolvePlaceholder( final String path, final String key, final Preferences preferences) { final String result = super.resolvePlaceholder(path, key, preferences); return convertPropertyValue(result); } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000074431360667575700401440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.4) * * @author Marcos Muíño García * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000102421360667575700405760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.4) * * @author Marcos Muíño García * @author Carlos Fernández * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ @Override protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptableServletContextPropertyPlaceholderConfigurer.java000066400000000000000000000107321360667575700435140ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.properties; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt servlet context parameter values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

<param-value>ENC(!"DGAS24FaIO$)</param-value>
*

* * @since 1.9.0 (existed in package org.jasypt.spring.properties since 1.7) * * @author Daniel Fernández * */ public final class EncryptableServletContextPropertyPlaceholderConfigurer extends ServletContextPropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * Spring's ServletContextPropertyPlaceholderConfigurer never creates a complete * map of properties, and so never really applies the "convertPropertyValue" method * to them. Instead it gets properties on the fly and returns them without conversion * (as of Spring 3.0.5). * * This fix makes sure that variables are decrypted before being returned. */ @Override protected String resolvePlaceholder(final String placeholder, final Properties props) { return convertPropertyValue(super.resolvePlaceholder(placeholder, props)); } } jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/000077500000000000000000000000001360667575700262135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/000077500000000000000000000000001360667575700304055ustar00rootroot00000000000000AbstractEncryptablePropertyLoadingBeanDefinitionParser.java000066400000000000000000000054701360667575700441520ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ abstract class AbstractEncryptablePropertyLoadingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptablePropertyLoadingBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateId() { return true; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { String location = element.getAttribute("location"); if (StringUtils.hasLength(location)) { String[] locations = StringUtils.commaDelimitedListToStringArray(location); builder.addPropertyValue("locations", locations); } String propertiesRef = element.getAttribute("properties-ref"); if (StringUtils.hasLength(propertiesRef)) { builder.addPropertyReference("properties", propertiesRef); } String fileEncoding = element.getAttribute("file-encoding"); if (StringUtils.hasLength(fileEncoding)) { builder.addPropertyReference("fileEncoding", fileEncoding); } String order = element.getAttribute("order"); if (StringUtils.hasLength(order)) { builder.addPropertyValue("order", Integer.valueOf(order)); } builder.addPropertyValue("ignoreResourceNotFound", Boolean.valueOf(element.getAttribute("ignore-resource-not-found"))); builder.addPropertyValue("localOverride", Boolean.valueOf(element.getAttribute("local-override"))); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); } } AbstractEncryptionBeanDefinitionParser.java000066400000000000000000000066211360667575700407700ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ abstract class AbstractEncryptionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptionBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateIdAsFallback() { return true; } protected final void processStringAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { builder.addPropertyValue(propertyName, attributeValue); } } protected final void processIntegerAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { try { final Integer attributeIntegerValue = Integer.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeIntegerValue); } catch (final NumberFormatException e) { throw new NumberFormatException( "Config attribute \"" + attributeName + "\" is not a valid integer"); } } } protected final void processBooleanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { final Boolean attributeBooleanValue = Boolean.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeBooleanValue); } } protected final void processBeanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String beanName = element.getAttribute(attributeName); if (StringUtils.hasText(beanName)) { builder.addPropertyReference(propertyName, beanName); } } } DigesterBeanDefinitionParser.java000066400000000000000000000111011360667575700367050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class DigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private final int digesterType; DigesterBeanDefinitionParser(final int digesterType) { super(); this.digesterType = digesterType; } @Override protected Class getBeanClass(final Element element) { return DigesterFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.digesterType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processBooleanAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } DigesterConfigBeanDefinitionParser.java000066400000000000000000000403341360667575700400450ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.digest.config.EnvironmentDigesterConfig; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.digest.config.SimpleStringDigesterConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class DigesterConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_ITERATIONS, PARAM_SALT_SIZE_BYTES, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, PARAM_USE_LENIENT_SALT_SIZE_CHECK, PARAM_POOL_SIZE })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE, PARAM_UNICODE_NORMALIZATION_IGNORED, PARAM_PREFIX, PARAM_SUFFIX })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_ITERATIONS_ENV_NAME = "iterations-env-name"; private static final String PARAM_ITERATIONS_SYS_PROPERTY_NAME = "iterations-sys-property-name"; private static final String PARAM_SALT_SIZE_BYTES_ENV_NAME = "salt-size-bytes-env-name"; private static final String PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME = "salt-size-bytes-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME = "invert-position-of-salt-in-message-before-digesting-env-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME = "invert-position-of-salt-in-message-before-digesting-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME = "invert-position-of-plain-salt-in-encryption-results-env-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME = "invert-position-of-plain-salt-in-encryption-results-sys-property-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME = "use-lenient-salt-size-check-env-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME = "use-lenient-salt-size-check-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_ITERATIONS_ENV_NAME, PARAM_ITERATIONS_SYS_PROPERTY_NAME, PARAM_SALT_SIZE_BYTES_ENV_NAME, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME = "unicode-normalization-ignored-env-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME = "unicode-normalization-ignored-sys-property-name"; private static final String PARAM_PREFIX_ENV_NAME = "prefix-env-name"; private static final String PARAM_PREFIX_SYS_PROPERTY_NAME = "prefix-sys-property-name"; private static final String PARAM_SUFFIX_ENV_NAME = "suffix-env-name"; private static final String PARAM_SUFFIX_SYS_PROPERTY_NAME = "suffix-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, PARAM_PREFIX_ENV_NAME, PARAM_PREFIX_SYS_PROPERTY_NAME, PARAM_SUFFIX_ENV_NAME, PARAM_SUFFIX_SYS_PROPERTY_NAME })); DigesterConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_ITERATIONS_ENV_NAME, "iterationsEnvName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_ENV_NAME, "saltSizeBytesEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, "invertPositionOfSaltInMessageBeforeDigestingEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, "invertPositionOfPlainSaltInEncryptionResultsEnvName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, "useLenientSaltSizeCheckEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_ITERATIONS_SYS_PROPERTY_NAME, "iterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, "saltSizeBytesSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, "invertPositionOfSaltInMessageBeforeDigestingSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, "invertPositionOfPlainSaltInEncryptionResultsSysPropertyName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, "useLenientSaltSizeCheckSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, "unicodeNormalizationIgnoredEnvName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, "unicodeNormalizationIgnoredSysPropertyName"); processStringAttribute(element, builder, PARAM_PREFIX_ENV_NAME, "prefixEnvName"); processStringAttribute(element, builder, PARAM_PREFIX_SYS_PROPERTY_NAME, "prefixSysPropertyName"); processStringAttribute(element, builder, PARAM_SUFFIX_ENV_NAME, "suffixEnvName"); processStringAttribute(element, builder, PARAM_SUFFIX_SYS_PROPERTY_NAME, "suffixSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringDigesterConfig.class; } if (isEnvironmentConfig) { return EnvironmentDigesterConfig.class; } if (isStringConfig) { return SimpleStringDigesterConfig.class; } return SimpleDigesterConfig.class; } } DigesterFactoryBean.java000066400000000000000000000323231360667575700350600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.PooledByteDigester; import org.jasypt.digest.PooledStringDigester; import org.jasypt.digest.StandardByteDigester; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.StringDigester; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating digester objects from the encryption namespace * elements. Do not use directly. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class DigesterFactoryBean implements FactoryBean, InitializingBean { static final int DIGESTER_TYPE_BYTE = 0; static final int DIGESTER_TYPE_STRING = 1; private final int digesterType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private DigesterConfig config = null; private boolean iterationsSet = false; private Integer iterations = null; private boolean invertPositionOfPlainSaltInEncryptionResultsSet = false; private Boolean invertPositionOfPlainSaltInEncryptionResults = null; private boolean invertPositionOfSaltInMessageBeforeDigestingSet = false; private Boolean invertPositionOfSaltInMessageBeforeDigesting = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean saltSizeBytesSet = false; private Integer saltSizeBytes = null; private boolean useLenientSaltSizeCheckSet = false; private Boolean useLenientSaltSizeCheck = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; private boolean unicodeNormalizationIgnoredSet = false; private Boolean unicodeNormalizationIgnored = null; private boolean prefixSet = false; private String prefix = null; private boolean suffixSet = false; private String suffix = null; public DigesterFactoryBean(final int encryptorType) { super(); this.digesterType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final DigesterConfig config) { this.config = config; this.configSet = true; } public void setIterations(final Integer iterations) { this.iterations = iterations; this.iterationsSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setInvertPositionOfPlainSaltInEncryptionResults( final Boolean invertPositionOfPlainSaltInEncryptionResults) { this.invertPositionOfPlainSaltInEncryptionResults = invertPositionOfPlainSaltInEncryptionResults; this.invertPositionOfPlainSaltInEncryptionResultsSet = true; } public void setInvertPositionOfSaltInMessageBeforeDigesting( final Boolean invertPositionOfSaltInMessageBeforeDigesting) { this.invertPositionOfSaltInMessageBeforeDigesting = invertPositionOfSaltInMessageBeforeDigesting; this.invertPositionOfSaltInMessageBeforeDigestingSet = true; } public void setSaltSizeBytes(final Integer saltSizeBytes) { this.saltSizeBytes = saltSizeBytes; this.saltSizeBytesSet = true; } public void setUseLenientSaltSizeCheck(final Boolean useLenientSaltSizeCheck) { this.useLenientSaltSizeCheck = useLenientSaltSizeCheck; this.useLenientSaltSizeCheckSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public void setUnicodeNormalizationIgnored(final Boolean unicodeNormalizationIgnored) { this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; this.unicodeNormalizationIgnoredSet = true; } public void setPrefix(final String prefix) { this.prefix = prefix; this.prefixSet = true; } public void setSuffix(final String suffix) { this.suffix = suffix; this.suffixSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private synchronized Object computeObject() throws Exception { Object digester = null; if (isPooled()) { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new PooledByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new PooledStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( digester, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new StandardByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new StandardStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } if (this.algorithmSet) { final Statement st = new Statement( digester, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( digester, "setConfig", new Object[] { this.config }); st.execute(); } if (this.iterationsSet && this.iterations != null) { final Statement st = new Statement( digester, "setIterations", new Object[] { this.iterations }); st.execute(); } if (this.invertPositionOfSaltInMessageBeforeDigestingSet && this.invertPositionOfSaltInMessageBeforeDigesting != null) { final Statement st = new Statement( digester, "setInvertPositionOfSaltInMessageBeforeDigesting", new Object[] { this.invertPositionOfSaltInMessageBeforeDigesting }); st.execute(); } if (this.invertPositionOfPlainSaltInEncryptionResultsSet && this.invertPositionOfPlainSaltInEncryptionResults != null) { final Statement st = new Statement( digester, "setInvertPositionOfPlainSaltInEncryptionResults", new Object[] { this.invertPositionOfPlainSaltInEncryptionResults }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( digester, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( digester, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( digester, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.saltSizeBytesSet && this.saltSizeBytes != null) { final Statement st = new Statement( digester, "setSaltSizeBytes", new Object[] { this.saltSizeBytes }); st.execute(); } if (this.useLenientSaltSizeCheckSet && this.useLenientSaltSizeCheck != null) { final Statement st = new Statement( digester, "setUseLenientSaltSizeCheck", new Object[] { this.useLenientSaltSizeCheck }); st.execute(); } if (digester instanceof StringDigester) { if (this.stringOutputTypeSet) { final Statement st = new Statement( digester, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } if (this.unicodeNormalizationIgnoredSet) { final Statement st = new Statement( digester, "setUnicodeNormalizationIgnored", new Object[] { this.unicodeNormalizationIgnored }); st.execute(); } if (this.prefixSet) { final Statement st = new Statement( digester, "setPrefix", new Object[] { this.prefix }); st.execute(); } if (this.suffixSet) { final Statement st = new Statement( digester, "setSuffix", new Object[] { this.suffix }); st.execute(); } } return digester; } public Class getObjectType() { if (this.digesterType == DIGESTER_TYPE_BYTE) { return ByteDigester.class; } else if (this.digesterType == DIGESTER_TYPE_STRING) { return StringDigester.class; } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } EncryptablePropertiesBeanDefinitionParser.java000066400000000000000000000052421360667575700414750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.util.Properties; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertiesBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertiesBeanDefinitionParser() { super(); } @Override protected boolean isEligibleAttribute(final String attributeName) { return super.isEligibleAttribute(attributeName) && !SCOPE_ATTRIBUTE.equals(attributeName) && !ENCRYPTOR_ATTRIBUTE.equals(attributeName); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertiesFactoryBean.class; } @Override protected void doParse(final Element element, final ParserContext parserContext, final BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); Properties parsedProps = parserContext.getDelegate().parsePropsElement(element); builder.addPropertyValue("properties", parsedProps); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addPropertyReference("encryptor", encryptorBeanName); } } } EncryptablePropertiesFactoryBean.java000066400000000000000000000075221360667575700376420ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.io.IOException; import java.util.Properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.EncryptableProperties; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.support.PropertiesLoaderSupport; /** *

* Factory bean for creating encrptable properties objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptablePropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean, InitializingBean { private boolean singleton = true; private Properties singletonInstance; private Object encryptor = null; public EncryptablePropertiesFactoryBean() { super(); } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setEncryptor(final Object encryptor) { this.encryptor = encryptor; } public final void afterPropertiesSet() throws IOException { if (this.singleton) { this.singletonInstance = processEncryptable(mergeProperties()); } } public final Object getObject() throws IOException { if (this.singleton) { return this.singletonInstance; } return processEncryptable(mergeProperties()); } public Class getObjectType() { return EncryptableProperties.class; } private EncryptableProperties processEncryptable(final Properties props) { if (this.encryptor == null) { throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition cannot be null"); } if (this.encryptor instanceof TextEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((TextEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } else if (this.encryptor instanceof StringEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((StringEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition must be either " + "an org.jasypt.util.text.TextEncryptor or an org.jasypt.encryption.StringEncryptor " + "object. An object of class " + this.encryptor.getClass().getName() + " has been " + "specified instead."); } } EncryptablePropertyOverrideBeanDefinitionParser.java000066400000000000000000000041231360667575700426620ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.jasypt.spring3.properties.EncryptablePropertyOverrideConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertyOverrideBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertyOverrideBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertyOverrideConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreInvalidKeys", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptablePropertyPlaceholderBeanDefinitionParser.java000066400000000000000000000046071360667575700433340ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertyPlaceholderBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertyPlaceholderBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertyPlaceholderConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); String systemPropertiesModeName = element.getAttribute("system-properties-mode"); if (StringUtils.hasLength(systemPropertiesModeName)) { builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptionNamespaceHandler.java000066400000000000000000000205201360667575700364350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** *

* Namespace handler for jasypt's encryption namespace. *

*

* In order to use this namespace, add its XML schema declaration to your Spring * beans file like: *

* * <beans xmlns="http://www.springframework.org/schema/beans"
*        ...
*        xmlns:encryption="http://www.jasypt.org/schema/encryption"
*        ...
*        xsi:schemaLocation="http://www.springframework.org/schema/beans
*                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
*                            ...
*                            http://www.jasypt.org/schema/encryption
*                            http://www.jasypt.org/schema/encryption/jasypt-spring3-encryption-1.xsd
*                            ..."> *
*

* This namespace offers the following elements for creating instances of specific jasypt artifacts * and add them to the Spring application context: *

*
    *
  • Digesters *
      *
    • {@link org.jasypt.digest.config.DigesterConfig} (simple, string, environment): <encryption:digester-config/>
    • *
    • {@link org.jasypt.digest.ByteDigester} (pooled or standard, depending on selected pool size): <encryption:byte-digester/>
    • *
    • {@link org.jasypt.digest.StringDigester} (pooled or standard, depending on selected pool size): <encryption:string-digester/>
    • *
    • Util digester classes: *
        *
      • {@link org.jasypt.util.password.BasicPasswordEncryptor}: <encryption:basic-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.StrongPasswordEncryptor}: <encryption:strong-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.ConfigurablePasswordEncryptor}: <encryption:configurable-password-encryptor/>
      • *
      *
    • *
    *
  • *
  • PBE Encryption *
      *
    • {@link org.jasypt.encryption.pbe.config.PBEConfig} (simple, string, environment): <encryption:encryptor-config/>
    • *
    • {@link org.jasypt.encryption.ByteEncryptor} (pooled or standard, depending on selected pool size): <encryption:byte-encryptor/>
    • *
    • {@link org.jasypt.encryption.StringEncryptor} (pooled or standard, depending on selected pool size): <encryption:string-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigIntegerEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-integer-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigDecimalEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-decimal-encryptor/>
    • *
    • Util encryptor classes: *
        *
      • {@link org.jasypt.util.text.BasicTextEncryptor}: <encryption:basic-text-encryptor/>
      • *
      • {@link org.jasypt.util.text.StrongTextEncryptor}: <encryption:strong-text-encryptor/>
      • *
      *
    • *
    *
  • *
  • Properties management *
      *
    • {@link org.jasypt.properties.EncryptableProperties} (equivalent to <util:properties/> adding property decryption): <encryption:encryptable-properties/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer} (equivalent to <context:property-placeholder/> adding property decryption): <encryption:encryptable-property-placeholder/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyOverrideConfigurer} (equivalent to <context:property-override/> adding property decryption): <encryption:encryptable-property-override/>
    • *
    *
  • *
* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptionNamespaceHandler extends NamespaceHandlerSupport { public EncryptionNamespaceHandler() { super(); } public void init() { registerBeanDefinitionParser("encryptor-config", new EncryptorConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BYTE)); registerBeanDefinitionParser("string-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_STRING)); registerBeanDefinitionParser("big-decimal-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_DECIMAL)); registerBeanDefinitionParser("big-integer-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_INTEGER)); registerBeanDefinitionParser("basic-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("digester-config", new DigesterConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_BYTE)); registerBeanDefinitionParser("string-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_STRING)); registerBeanDefinitionParser("basic-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("configurable-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_CONFIGURABLE)); registerBeanDefinitionParser("encryptable-properties", new EncryptablePropertiesBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-placeholder", new EncryptablePropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-override", new EncryptablePropertyOverrideBeanDefinitionParser()); } } EncryptorBeanDefinitionParser.java000066400000000000000000000067411360667575700371420ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private final int encryptorType; EncryptorBeanDefinitionParser(final int encryptorType) { super(); this.encryptorType = encryptorType; } @Override protected Class getBeanClass(final Element element) { return EncryptorFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.encryptorType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } EncryptorConfigBeanDefinitionParser.java000066400000000000000000000274211360667575700402660ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.encryption.pbe.config.EnvironmentPBEConfig; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; import org.jasypt.encryption.pbe.config.SimplePBEConfig; import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptorConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_IV_GENERATOR_CLASS_NAME = "iv-generator-class-name"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_KEY_OBTENTION_ITERATIONS, PARAM_PASSWORD, PARAM_POOL_SIZE, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_IV_GENERATOR_BEAN, PARAM_IV_GENERATOR_CLASS_NAME })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME = "key-obtention-iterations-env-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME = "key-obtention-iterations-sys-property-name"; private static final String PARAM_PASSWORD_ENV_NAME = "password-env-name"; private static final String PARAM_PASSWORD_SYS_PROPERTY_NAME = "password-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME = "iv-generator-class-name-env-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "iv-generator-class-name-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, PARAM_PASSWORD_ENV_NAME, PARAM_PASSWORD_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME })); EncryptorConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME, "ivGeneratorClassName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, "keyObtentionIterationsEnvName"); processStringAttribute(element, builder, PARAM_PASSWORD_ENV_NAME, "passwordEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, "ivGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, "keyObtentionIterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_PASSWORD_SYS_PROPERTY_NAME, "passwordSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "ivGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringPBEConfig.class; } if (isEnvironmentConfig) { return EnvironmentPBEConfig.class; } if (isStringConfig) { return SimpleStringPBEConfig.class; } return SimplePBEConfig.class; } } EncryptorFactoryBean.java000066400000000000000000000256501360667575700353040ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PooledPBEByteEncryptor; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating encryptor objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptorFactoryBean implements FactoryBean, InitializingBean { static final int ENCRYPTOR_TYPE_BYTE = 0; static final int ENCRYPTOR_TYPE_STRING = 1; static final int ENCRYPTOR_TYPE_BIG_DECIMAL = 2; static final int ENCRYPTOR_TYPE_BIG_INTEGER = 3; private final int encryptorType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private PBEConfig config = null; private boolean keyObtentionIterationsSet = false; private Integer keyObtentionIterations = null; private boolean passwordSet = false; private String password = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean ivGeneratorSet = false; private IvGenerator ivGenerator = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; public EncryptorFactoryBean(final int encryptorType) { super(); this.encryptorType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final PBEConfig config) { this.config = config; this.configSet = true; } public void setKeyObtentionIterations(final Integer keyObtentionIterations) { this.keyObtentionIterations = keyObtentionIterations; this.keyObtentionIterationsSet = true; } public void setPassword(final String password) { this.password = password; this.passwordSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setIvGenerator(final IvGenerator ivGenerator) { this.ivGenerator = ivGenerator; this.ivGeneratorSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private Object computeObject() throws Exception { Object encryptor = null; if (isPooled()) { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new PooledPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new PooledPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new PooledPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new PooledPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( encryptor, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new StandardPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new StandardPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new StandardPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new StandardPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } if (this.algorithmSet) { final Statement st = new Statement( encryptor, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( encryptor, "setConfig", new Object[] { this.config }); st.execute(); } if (this.keyObtentionIterationsSet && this.keyObtentionIterations != null) { final Statement st = new Statement( encryptor, "setKeyObtentionIterations", new Object[] { this.keyObtentionIterations }); st.execute(); } if (this.passwordSet) { final Statement st = new Statement( encryptor, "setPassword", new Object[] { this.password }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( encryptor, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( encryptor, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( encryptor, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.ivGeneratorSet) { final Statement st = new Statement( encryptor, "setIvGenerator", new Object[] { this.ivGenerator }); st.execute(); } if (this.stringOutputTypeSet && encryptor instanceof PBEStringEncryptor) { final Statement st = new Statement( encryptor, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } return encryptor; } public Class getObjectType() { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { return PBEByteEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { return PBEStringEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { return PBEBigDecimalEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { return PBEBigIntegerEncryptor.class; } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } UtilDigesterBeanDefinitionParser.java000066400000000000000000000064011360667575700375520ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.StrongPasswordEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class UtilDigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; static final int UTIL_TYPE_CONFIGURABLE = 2; private final int utilType; UtilDigesterBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_CONFIGURABLE) { return ConfigurablePasswordEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } UtilEncryptorBeanDefinitionParser.java000066400000000000000000000046061360667575700377760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.xml.encryption; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class UtilEncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_PASSWORD = "password"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; private final int utilType; UtilEncryptorBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicTextEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongTextEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_PASSWORD, "password"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } jasypt-spring3-encryption-1.xsd000066400000000000000000001207171360667575700363010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/java/org/jasypt/spring3/xml/encryption jasypt-jasypt-1.9.3/jasypt-spring3/src/main/metainf/000077500000000000000000000000001360667575700224275ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/main/metainf/spring.handlers000066400000000000000000000001461360667575700254540ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption=org.jasypt.spring3.xml.encryption.EncryptionNamespaceHandler jasypt-jasypt-1.9.3/jasypt-spring3/src/main/metainf/spring.schemas000066400000000000000000000002131360667575700252720ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption/jasypt-spring3-encryption-1.xsd=org/jasypt/spring3/xml/encryption/jasypt-spring3-encryption-1.xsd jasypt-jasypt-1.9.3/jasypt-spring3/src/test/000077500000000000000000000000001360667575700210375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/000077500000000000000000000000001360667575700217605ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/000077500000000000000000000000001360667575700225475ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/000077500000000000000000000000001360667575700240615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring/000077500000000000000000000000001360667575700253635ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring/properties/000077500000000000000000000000001360667575700275575ustar00rootroot00000000000000EncryptablePropertyPlaceholderConfigurerTest.java000066400000000000000000000142601360667575700414120ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring/propertiespackage org.jasypt.spring.properties; import junit.framework.TestCase; import java.util.HashMap; import java.util.Map; import org.jasypt.encryption.StringEncryptor; import org.jasypt.util.text.TextEncryptor; /* * ==Test resolveSystemProperty for encrypted env var== * * I don't have a great way to test the decryption of encrypted env var without requiring the test harness (surefire, IDE etc) * to have specified an encrypted environment variable. Here are a few options * - reflection hack to change the underlying system env map - * http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java. THis is what spring does to * test the propertyplaceholderconfigurer: * https://src.springframework.org/svn/spring-framework/trunk/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java * - extract the call to super.resolveSystemProperty(key) in resolveSystemProperty to a protected method and the test * will use a testspecifc subclass (http://xunitpatterns.com/Test-Specific%20Subclass.html) that overrides that method. * * However, i really don't think it is that big of a deal. The functionality responsible for getting system/env values * is defined in the super. All this class does is check to see if they have the encryption delimiters. I am pretty sure * I already went overboard on the test - ~100 lines of test for 3 lines of production code. * * User: carlos fernandez * Date: 6/28/11 * Time: 10:38 PM */ public class EncryptablePropertyPlaceholderConfigurerTest extends TestCase { //duplicated prefix suffix values in PropertyValueEncryptionUtils because PVEU constants are private private static final String ENCRYPTED_VALUE_PREFIX = "ENC("; private static final String ENCRYPTED_VALUE_SUFFIX = ")"; private String expectedDecryptedValue; private String encryptedValue; private String encryptedValueWithDelimiters; private String encryptedSysPropKey; private String unencryptedSysPropKey; private String unencryptedValue; public void setUp() { encryptedSysPropKey = "thisIsAnEncryptedSysPropertyKey"; encryptedValue = "encryptedString"; encryptedValueWithDelimiters = ENCRYPTED_VALUE_PREFIX + this.encryptedValue + ENCRYPTED_VALUE_SUFFIX; expectedDecryptedValue = "clearText"; System.setProperty(encryptedSysPropKey, encryptedValueWithDelimiters); unencryptedSysPropKey = "thisIsAnUNEncryptedSysPropertyKey"; unencryptedValue = "thisIsARegularString"; System.setProperty(unencryptedSysPropKey, unencryptedValue); } public void testConvertPropertyValueNotEncrypted() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, eppc.convertPropertyValue(unencryptedValue)); } public void testConvertPropertyValueDecryptWithStringEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testConvertPropertyValueDecryptWithTextEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testResolveSystemPropertyNullSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertNull(ppc.resolveSystemProperty("foofoofoo")); } public void testResolveSystemPropertyEncryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, ppc.resolveSystemProperty(encryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, ppc.resolveSystemProperty(unencryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedEnvVar() throws Exception { //the expectation is that the system has the HOME env var String unencryptedEnvVarKey = "HOME";//this is expected to exist on windows and unix systems String unencryptedEnvVarValue = System.getenv(unencryptedEnvVarKey); //lets make sure the env variable is set & is not null assertNotNull("no home env variable found", unencryptedEnvVarValue); EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); //allow ppc can check env vars ppc.setSearchSystemEnvironment(true); assertEquals(unencryptedEnvVarValue, ppc.resolveSystemProperty(unencryptedEnvVarKey)); } private EncryptablePropertyPlaceholderConfigurer createPPCWithTextEncryptor() { StubTextEncryptor textEncryptor = new StubTextEncryptor(); textEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(textEncryptor); } private EncryptablePropertyPlaceholderConfigurer createPPCWithStringEncryptor() { StubStringEncryptor stringEncryptor = new StubStringEncryptor(); stringEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(stringEncryptor); } abstract class StubEncryptor { private Map decryptMap = new HashMap(); public String decrypt(String encryptedMessage) { return (String)this.decryptMap.get(encryptedMessage); } public String encrypt(String message) { throw new UnsupportedOperationException(); } public void addDecryption(String encrypted, String expectedDecryption) { this.decryptMap.put(encrypted, expectedDecryption); } } class StubStringEncryptor extends StubEncryptor implements StringEncryptor{} class StubTextEncryptor extends StubEncryptor implements TextEncryptor{} } jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring3/000077500000000000000000000000001360667575700254465ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring3/configuration/000077500000000000000000000000001360667575700303155ustar00rootroot00000000000000ConfigurationProperties.java000066400000000000000000000034321360667575700357670ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring3/configuration/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.configuration; /** * * @author Soraya Sánchez * */ public class ConfigurationProperties { private String location; private String locatinPlainValue; private String locationEncryptedValue; public ConfigurationProperties() { super(); } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getLocatinPlainValue() { return locatinPlainValue; } public void setLocationPlainValue(String locatinPlainValue) { this.locatinPlainValue = locatinPlainValue; } public String getLocationEncryptedValue() { return locationEncryptedValue; } public void setLocationEncryptedValue(String locatinEncryptedValue) { this.locationEncryptedValue = locatinEncryptedValue; } } jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring3/test/000077500000000000000000000000001360667575700264255ustar00rootroot00000000000000TestSpringConfiguration.java000066400000000000000000000111021360667575700340360ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/java/org/jasypt/spring3/test/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3.test; import junit.framework.TestCase; import org.apache.commons.lang.ArrayUtils; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.StringDigester; import org.jasypt.encryption.ByteEncryptor; import org.jasypt.encryption.StringEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.spring3.configuration.ConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * * @author Soraya Sánchez * */ public class TestSpringConfiguration extends TestCase { private final static String CONFIGURATION_ENCRYPTOR_BEAN_NAME = "configurationEncryptor"; private final static String CONFIGURATION_PROPERTIES_BEAN_NAME = "configurationProperties"; private final static String BYTE_ENCRYPTOR_BEAN_NAME = "be"; private final static String STRING_ENCRYPTOR_BEAN_NAME = "se"; private final static String STRING_DIGESTER_BEAN_NAME = "sd"; private static ApplicationContext ctx; protected void setUp() throws Exception { super.setUp(); initSpring(); } public static void initSpring() { ctx = new ClassPathXmlApplicationContext(new String[] {"spring.xml"}); } public void testEncryptedProperties() throws Exception { ConfigurationProperties configurationProperties = (ConfigurationProperties) ctx.getBean(CONFIGURATION_PROPERTIES_BEAN_NAME); StringEncryptor stringEncryptor = (StringEncryptor) ctx.getBean(CONFIGURATION_ENCRYPTOR_BEAN_NAME); assertEquals(configurationProperties.getLocation(), configurationProperties.getLocatinPlainValue()); assertEquals(stringEncryptor.decrypt(configurationProperties.getLocationEncryptedValue()), configurationProperties.getLocation()); } public void testNamespace() throws Exception { StandardPBEByteEncryptor standardPBEByteEncryptor = new StandardPBEByteEncryptor(); standardPBEByteEncryptor.setPassword("jasypt"); standardPBEByteEncryptor.setAlgorithm("PBEWithMD5AndDES"); ByteEncryptor byteEncryptor = (ByteEncryptor) ctx.getBean(BYTE_ENCRYPTOR_BEAN_NAME); assertTrue(ArrayUtils.isEquals(new byte[] {5, 7, 13}, standardPBEByteEncryptor.decrypt(byteEncryptor.encrypt(new byte[] {5, 7, 13})))); StandardPBEStringEncryptor standardPBEStringEncryptor = new StandardPBEStringEncryptor(); standardPBEStringEncryptor.setPassword("jasypt"); standardPBEStringEncryptor.setAlgorithm("PBEWithMD5AndDES"); standardPBEStringEncryptor.setStringOutputType("hexadecimal"); StringEncryptor stringEncryptor = (StringEncryptor) ctx.getBean(STRING_ENCRYPTOR_BEAN_NAME); assertEquals("jasypt", standardPBEStringEncryptor.decrypt(stringEncryptor.encrypt("jasypt"))); StandardStringDigester standardStringDigester = new StandardStringDigester(); standardStringDigester.setAlgorithm("SHA-1"); standardStringDigester.setStringOutputType("hexa"); StringDigester stringDigester = (StringDigester) ctx.getBean(STRING_DIGESTER_BEAN_NAME); assertTrue(stringDigester.matches("jasypt", standardStringDigester.digest("jasypt"))); assertTrue(standardStringDigester.matches("jasypt", stringDigester.digest("jasypt"))); } } jasypt-jasypt-1.9.3/jasypt-spring3/src/test/resources/000077500000000000000000000000001360667575700230515ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring3/src/test/resources/props.properties000066400000000000000000000001731360667575700263330ustar00rootroot00000000000000location=ENC(v0z0uGQRucwfBau0e+gB6A\=\=) location.plain.value=Spain location.encrypted.value=v0z0uGQRucwfBau0e+gB6A\=\= jasypt-jasypt-1.9.3/jasypt-spring3/src/test/resources/spring.xml000066400000000000000000000070121360667575700250750ustar00rootroot00000000000000 jasypt-jasypt-1.9.3/jasypt-spring31-testapp/000077500000000000000000000000001360667575700210305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/.gitignore000066400000000000000000000000721360667575700230170ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring31-testapp/pom.xml000066400000000000000000000216361360667575700223550ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring31-testapp war 201905 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone src/main/resources src/main/java **/*.properties **/*.xml **/*.html org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 org.apache.maven.plugins maven-resources-plugin 2.5 ISO-8859-1 org.jasypt jasypt 1.9.3 compile org.jasypt jasypt-spring31 1.9.3 compile javax.servlet servlet-api 2.5 provided org.springframework spring-core 3.1.0.RELEASE compile org.springframework spring-context 3.1.0.RELEASE compile org.springframework spring-beans 3.1.0.RELEASE compile org.springframework spring-aop 3.1.0.RELEASE compile org.springframework spring-aspects 3.1.0.RELEASE compile org.springframework spring-expression 3.1.0.RELEASE compile org.springframework spring-web 3.1.0.RELEASE compile org.springframework spring-webmvc 3.1.0.RELEASE compile javax.validation validation-api 1.0.0.GA compile org.hibernate hibernate-validator-annotation-processor 4.1.0.Final org.slf4j slf4j-api 1.6.1 compile org.slf4j slf4j-log4j12 1.6.1 compile log4j log4j 1.2.15 compile com.sun.jdmk jmxtools com.sun.jmx jmxri javax.jms jms javax.servlet jsp-api 2.0 provided javax.servlet jstl 1.1.2 compile taglibs standard 1.1.2 compile jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/000077500000000000000000000000001360667575700216175ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/000077500000000000000000000000001360667575700225435ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/000077500000000000000000000000001360667575700234645ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/000077500000000000000000000000001360667575700242535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/jasypt/000077500000000000000000000000001360667575700255655ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/jasypt/spring3testapp/000077500000000000000000000000001360667575700305535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/jasypt/spring3testapp/web/000077500000000000000000000000001360667575700313305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/jasypt/spring3testapp/web/controller/000077500000000000000000000000001360667575700335135ustar00rootroot00000000000000Index.java000066400000000000000000000130601360667575700353460ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/java/org/jasypt/spring3testapp/web/controller/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring3testapp.web.controller; import java.util.Properties; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.StringDigester; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Index { @Autowired private PBEByteEncryptor enc1; @Autowired private PBEBigDecimalEncryptor enc3; @Autowired private PBEBigIntegerEncryptor enc4; @Autowired private PBEStringEncryptor encAES; @Autowired private BasicTextEncryptor bte; @Autowired private StrongTextEncryptor ste; @Autowired private StringDigester sd; @Autowired private ByteDigester bd; @Autowired private PasswordEncryptor bpe; @Autowired @Qualifier("eprop1") private Properties eprop1; @Autowired private ApplicationContext appCtx; @Autowired @Qualifier("eprop2") private Properties eprop2; @Value("${city.name}") private String cityName; @Value("${country.name}") private String countryName; public Index() { super(); } @RequestMapping({"/"}) public String show(final ModelMap model) { final byte[] mba = "Hello!".getBytes(); final byte[] encMba = this.enc1.encrypt(mba); model.addAttribute("encMba", new String(encMba) + " | " + enc1.getClass().getName()); final StandardPBEStringEncryptor enctest = new StandardPBEStringEncryptor(); enctest.setPassword("jasypt"); enctest.setAlgorithm("PBEWithMD5AndTripleDES"); enctest.setStringOutputType("hexa"); enctest.setKeyObtentionIterations(20); System.out.println("BigDecimal: " + enc3.getClass().getName()); System.out.println("BigInteger: " + enc4.getClass().getName()); String bteE = bte.encrypt("hello!"); System.out.println("Basic encryptor: " + bte.getClass().getName() + bteE + " -> " + bte.decrypt(bteE)); String steE = ste.encrypt("hello!"); System.out.println("Strong encryptor: " + ste.getClass().getName() + steE + " -> " + ste.decrypt(steE)); String encAESe = encAES.encrypt("hello!"); System.out.println("AES: " + encAES.getClass().getName() + encAESe + " -> " + encAES.decrypt(encAESe)); model.addAttribute("encAES", new String(encAESe) + " | " + encAES.getClass().getName()); System.out.println(sd.digest("myPassword") + " | " + sd.getClass().getName()); System.out.println(new String(bd.digest(mba)) + " | " + bd.getClass().getName()); final String ep = bpe.encryptPassword("HELLO!!"); System.out.println(ep + " | " + bpe.getClass().getName()); final ConfigurablePasswordEncryptor configurablePasswordEncryptor = new ConfigurablePasswordEncryptor(); configurablePasswordEncryptor.setAlgorithm("SHA-1"); configurablePasswordEncryptor.setStringOutputType("0x"); System.out.println(configurablePasswordEncryptor.checkPassword("HELLO!!", ep)); System.out.println(this.eprop1); System.out.println(this.eprop2); System.out.println("----------"); System.out.println(this.eprop1.getProperty("prop1")); System.out.println(this.eprop1.getProperty("prop2")); System.out.println("Existing digester: " + System.identityHashCode(this.sd)); StringDigester stex = (StringDigester) appCtx.getBean("sd1"); System.out.println("First digester: " + System.identityHashCode(stex)); stex = (StringDigester) appCtx.getBean("sd1"); System.out.println("Second digester: " + System.identityHashCode(stex)); System.out.println("City name: " + this.cityName); System.out.println("Country name: " + this.countryName); return "index"; } } jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/resources/000077500000000000000000000000001360667575700245555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/resources/log4j.properties000066400000000000000000000004061360667575700277120ustar00rootroot00000000000000log4j.rootLogger = WARN, stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p [%c{1}] (%F:%L) - %m%n jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/resources/some.properties000066400000000000000000000001121360667575700276300ustar00rootroot00000000000000country.name=ENC(zl94ORjq8JUSN/c5xGgVxomrMd5bf9K4) city.name=Penguin City jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/000077500000000000000000000000001360667575700240215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/META-INF/000077500000000000000000000000001360667575700251615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/META-INF/MANIFEST.MF000066400000000000000000000000471360667575700266140ustar00rootroot00000000000000Manifest-Version: 1.0 Class-Path: jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/WEB-INF/000077500000000000000000000000001360667575700250505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/WEB-INF/spring-servlet.xml000066400000000000000000000113211360667575700305540ustar00rootroot00000000000000 something ENC(JhuIj9BJvw7nEix0n4oM/VG0kgOTK51p4E1vzEWn65Nc7y8EfLomhCStYBNSyR4J) something-two jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/WEB-INF/templates/000077500000000000000000000000001360667575700270465ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/WEB-INF/templates/index.jsp000066400000000000000000000013521360667575700306740ustar00rootroot00000000000000<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %><%@ taglib prefix="s" uri="http://www.springframework.org/tags" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Jasypt Spring3 Test Application

This is a JSP

jasypt-jasypt-1.9.3/jasypt-spring31-testapp/src/main/webapp/WEB-INF/web.xml000066400000000000000000000015731360667575700263550ustar00rootroot00000000000000 jasypt-spring3-testapp 60 spring org.springframework.web.servlet.DispatcherServlet 1 spring / index jasypt-jasypt-1.9.3/jasypt-spring31/000077500000000000000000000000001360667575700173525ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/.gitignore000066400000000000000000000000721360667575700213410ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring31/BUILD.txt000066400000000000000000000014501360667575700207520ustar00rootroot00000000000000 Building JASYPT-SPRING3 ----------------------- To build JASYPT-SPRING3 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRING3 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-spring3-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-spring3/{version}/jasypt-spring3-{version}.jar Generating Javadoc for JASYPT-SPRING3 ------------------------------------- If you wish to generate the javadoc for JASYPT-SPRING3, execute this from the JASYPT-SPRING3 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-spring31/ChangeLog.txt000066400000000000000000000042171360667575700217460ustar00rootroot000000000000001.9.3 ===== - Fixed #32: encryption works but decryption does not, Java 8 (JCE jars installed). Added support for initialization vectors needed for AES encryption and decryption since Java 8. 1.9.2 ===== - Fixed EncryptablePreferencesPlaceholderConfigurer not applying value decryption when needed. 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-spring31 package from previous monolithic jasypt module. - Renamed org.jasypt.spring package as org.jasypt.spring31, and deprecated the classes in the old package. - Created the "encryption" XML namespace, containing tags for: * Encryptors * PBE encryptor config objects: * PBE byte encryptor objects: * PBE string encryptor objects: * PBE big decimal encryptor objects: * PBE big integer encryptor objects: * Digesters * Digester config objects: * Digester byte digester objects: * Digester string digester objects: * Util encryptors/digesters * Basic text encryptor objects: * Strong text encryptor objects: * Basic password encryptor objects: * Strong password encryptor objects: * Configurable password encryptor objects: * Encryptable properties * Encryptable properties objects (java.util.Properties): * Encryptable property placeholder configurer: * Encryptable property override configurer: - Created an EncryptablePropertiesPropertySource class implementing the new PropertySource interface for using encrypted properties files as a possible properties source in the new environment configuration system. jasypt-jasypt-1.9.3/jasypt-spring31/LICENSE.txt000066400000000000000000000261361360667575700212050ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-spring31/NOTICE.txt000066400000000000000000000072671360667575700211100ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-spring31/README.txt000066400000000000000000000006111360667575700210460ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-spring31/RELEASING.txt000066400000000000000000000023061360667575700214250ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-spring31/USAGE.txt000066400000000000000000000011731360667575700207610ustar00rootroot00000000000000 Using JASYPT-SPRING3 from Maven 2 --------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-spring3 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-spring31/pom.xml000066400000000000000000000207671360667575700207030ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring31 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone true src/main/java **/*.xsd src/main/resources . META-INF LICENSE.txt NOTICE.txt src/main/metainf META-INF spring.handlers spring.schemas src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework spring-core 3.1.0.RELEASE provided true org.springframework spring-beans 3.1.0.RELEASE provided true org.springframework spring-web 3.1.0.RELEASE provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-spring31/src/000077500000000000000000000000001360667575700201415ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/000077500000000000000000000000001360667575700210655ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/000077500000000000000000000000001360667575700220065ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/000077500000000000000000000000001360667575700225755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/000077500000000000000000000000001360667575700241075ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/000077500000000000000000000000001360667575700255555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/000077500000000000000000000000001360667575700277515ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000111611360667575700413560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import java.util.Properties; import java.util.prefs.Preferences; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.util.Properties) */ @Override protected String resolvePlaceholder(final String placeholder, final Properties props) { final String result = super.resolvePlaceholder(placeholder, props); return convertPropertyValue(result); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.lang.String, java.util.prefs.Preferences) */ @Override protected String resolvePlaceholder( final String path, final String key, final Preferences preferences) { final String result = super.resolvePlaceholder(path, key, preferences); return convertPropertyValue(result); } } EncryptablePropertiesPropertySource.java000066400000000000000000000060031360667575700400070ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import java.util.Properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.EncryptableProperties; import org.jasypt.util.text.TextEncryptor; import org.springframework.core.env.PropertiesPropertySource; /** * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptablePropertiesPropertySource extends PropertiesPropertySource { public EncryptablePropertiesPropertySource(final String name, final EncryptableProperties props) { super(name, props); } public EncryptablePropertiesPropertySource(final String name, final Properties props, final TextEncryptor encryptor) { super(name, processProperties(props, encryptor)); } public EncryptablePropertiesPropertySource(final String name, final Properties props, final StringEncryptor encryptor) { super(name, processProperties(props, encryptor)); } private static Properties processProperties(final Properties props, final TextEncryptor encryptor) { if (props == null) { return null; } if (props instanceof EncryptableProperties) { throw new IllegalArgumentException( "Properties object already is an " + EncryptableProperties.class.getName() + " object. No encryptor should be specified."); } final EncryptableProperties encryptableProperties = new EncryptableProperties(encryptor); encryptableProperties.putAll(props); return encryptableProperties; } private static Properties processProperties(final Properties props, final StringEncryptor encryptor) { if (props == null) { return null; } if (props instanceof EncryptableProperties) { throw new IllegalArgumentException( "Properties object already is an " + EncryptableProperties.class.getName() + " object. No encryptor should be specified."); } final EncryptableProperties encryptableProperties = new EncryptableProperties(encryptor); encryptableProperties.putAll(props); return encryptableProperties; } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000073501360667575700403030ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 * * @author Marcos Muíño García * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000101551360667575700407430ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.0 * * @author Marcos Muíño García * @author Carlos Fernández * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ @Override protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptablePropertySourcesPlaceholderConfigurer.java000066400000000000000000000105021360667575700423030ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import java.io.IOException; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; /** *

*

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptablePropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /* * This flag will keep track of whether the "convertProperties()" method * (which decrypts encrypted property entries) has already been called * or not. * * This is needed because of a bug in Spring 3.1.0.RELEASE: * https://jira.springsource.org/browse/SPR-8928 * * This flag will avoid calling "convertProperties()" twice once this * bug has been solved. */ private boolean alreadyConverted = false; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertySourcesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertySourcesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * This is needed because of https://jira.springsource.org/browse/SPR-8928 */ @Override protected Properties mergeProperties() throws IOException { final Properties mergedProperties = super.mergeProperties(); convertProperties(mergedProperties); return mergedProperties; } /* * This is needed because of https://jira.springsource.org/browse/SPR-8928 */ @Override protected void convertProperties(final Properties props) { if (!this.alreadyConverted) { super.convertProperties(props); this.alreadyConverted = true; } } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptableServletContextPropertyPlaceholderConfigurer.java000066400000000000000000000106271360667575700436610ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.properties; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt servlet context parameter values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

<param-value>ENC(!"DGAS24FaIO$)</param-value>
*

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptableServletContextPropertyPlaceholderConfigurer extends ServletContextPropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableServletContextPropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptableServletContextPropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * Spring's ServletContextPropertyPlaceholderConfigurer never creates a complete * map of properties, and so never really applies the "convertPropertyValue" method * to them. Instead it gets properties on the fly and returns them without conversion * (as of Spring 3.0.5). * * This fix makes sure that variables are decrypted before being returned. */ protected String resolvePlaceholder(final String placeholder, final Properties props) { return convertPropertyValue(super.resolvePlaceholder(placeholder, props)); } } jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/000077500000000000000000000000001360667575700263555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/000077500000000000000000000000001360667575700305475ustar00rootroot00000000000000AbstractEncryptablePropertyLoadingBeanDefinitionParser.java000066400000000000000000000054711360667575700443150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ abstract class AbstractEncryptablePropertyLoadingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptablePropertyLoadingBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateId() { return true; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { String location = element.getAttribute("location"); if (StringUtils.hasLength(location)) { String[] locations = StringUtils.commaDelimitedListToStringArray(location); builder.addPropertyValue("locations", locations); } String propertiesRef = element.getAttribute("properties-ref"); if (StringUtils.hasLength(propertiesRef)) { builder.addPropertyReference("properties", propertiesRef); } String fileEncoding = element.getAttribute("file-encoding"); if (StringUtils.hasLength(fileEncoding)) { builder.addPropertyReference("fileEncoding", fileEncoding); } String order = element.getAttribute("order"); if (StringUtils.hasLength(order)) { builder.addPropertyValue("order", Integer.valueOf(order)); } builder.addPropertyValue("ignoreResourceNotFound", Boolean.valueOf(element.getAttribute("ignore-resource-not-found"))); builder.addPropertyValue("localOverride", Boolean.valueOf(element.getAttribute("local-override"))); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); } } AbstractEncryptionBeanDefinitionParser.java000066400000000000000000000066221360667575700411330ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ abstract class AbstractEncryptionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptionBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateIdAsFallback() { return true; } protected final void processStringAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { builder.addPropertyValue(propertyName, attributeValue); } } protected final void processIntegerAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { try { final Integer attributeIntegerValue = Integer.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeIntegerValue); } catch (final NumberFormatException e) { throw new NumberFormatException( "Config attribute \"" + attributeName + "\" is not a valid integer"); } } } protected final void processBooleanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { final Boolean attributeBooleanValue = Boolean.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeBooleanValue); } } protected final void processBeanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String beanName = element.getAttribute(attributeName); if (StringUtils.hasText(beanName)) { builder.addPropertyReference(propertyName, beanName); } } } DigesterBeanDefinitionParser.java000066400000000000000000000111021360667575700370500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class DigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private final int digesterType; DigesterBeanDefinitionParser(final int digesterType) { super(); this.digesterType = digesterType; } @Override protected Class getBeanClass(final Element element) { return DigesterFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.digesterType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processBooleanAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } DigesterConfigBeanDefinitionParser.java000066400000000000000000000403351360667575700402100ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.digest.config.EnvironmentDigesterConfig; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.digest.config.SimpleStringDigesterConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class DigesterConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_ITERATIONS, PARAM_SALT_SIZE_BYTES, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, PARAM_USE_LENIENT_SALT_SIZE_CHECK, PARAM_POOL_SIZE })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE, PARAM_UNICODE_NORMALIZATION_IGNORED, PARAM_PREFIX, PARAM_SUFFIX })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_ITERATIONS_ENV_NAME = "iterations-env-name"; private static final String PARAM_ITERATIONS_SYS_PROPERTY_NAME = "iterations-sys-property-name"; private static final String PARAM_SALT_SIZE_BYTES_ENV_NAME = "salt-size-bytes-env-name"; private static final String PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME = "salt-size-bytes-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME = "invert-position-of-salt-in-message-before-digesting-env-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME = "invert-position-of-salt-in-message-before-digesting-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME = "invert-position-of-plain-salt-in-encryption-results-env-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME = "invert-position-of-plain-salt-in-encryption-results-sys-property-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME = "use-lenient-salt-size-check-env-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME = "use-lenient-salt-size-check-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_ITERATIONS_ENV_NAME, PARAM_ITERATIONS_SYS_PROPERTY_NAME, PARAM_SALT_SIZE_BYTES_ENV_NAME, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME = "unicode-normalization-ignored-env-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME = "unicode-normalization-ignored-sys-property-name"; private static final String PARAM_PREFIX_ENV_NAME = "prefix-env-name"; private static final String PARAM_PREFIX_SYS_PROPERTY_NAME = "prefix-sys-property-name"; private static final String PARAM_SUFFIX_ENV_NAME = "suffix-env-name"; private static final String PARAM_SUFFIX_SYS_PROPERTY_NAME = "suffix-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, PARAM_PREFIX_ENV_NAME, PARAM_PREFIX_SYS_PROPERTY_NAME, PARAM_SUFFIX_ENV_NAME, PARAM_SUFFIX_SYS_PROPERTY_NAME })); DigesterConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_ITERATIONS_ENV_NAME, "iterationsEnvName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_ENV_NAME, "saltSizeBytesEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, "invertPositionOfSaltInMessageBeforeDigestingEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, "invertPositionOfPlainSaltInEncryptionResultsEnvName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, "useLenientSaltSizeCheckEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_ITERATIONS_SYS_PROPERTY_NAME, "iterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, "saltSizeBytesSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, "invertPositionOfSaltInMessageBeforeDigestingSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, "invertPositionOfPlainSaltInEncryptionResultsSysPropertyName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, "useLenientSaltSizeCheckSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, "unicodeNormalizationIgnoredEnvName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, "unicodeNormalizationIgnoredSysPropertyName"); processStringAttribute(element, builder, PARAM_PREFIX_ENV_NAME, "prefixEnvName"); processStringAttribute(element, builder, PARAM_PREFIX_SYS_PROPERTY_NAME, "prefixSysPropertyName"); processStringAttribute(element, builder, PARAM_SUFFIX_ENV_NAME, "suffixEnvName"); processStringAttribute(element, builder, PARAM_SUFFIX_SYS_PROPERTY_NAME, "suffixSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringDigesterConfig.class; } if (isEnvironmentConfig) { return EnvironmentDigesterConfig.class; } if (isStringConfig) { return SimpleStringDigesterConfig.class; } return SimpleDigesterConfig.class; } } DigesterFactoryBean.java000066400000000000000000000323241360667575700352230ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.PooledByteDigester; import org.jasypt.digest.PooledStringDigester; import org.jasypt.digest.StandardByteDigester; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.StringDigester; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating digester objects from the encryption namespace * elements. Do not use directly. *

* * @since 1.9.0 * * @author Daniel Fernández * */ public final class DigesterFactoryBean implements FactoryBean, InitializingBean { static final int DIGESTER_TYPE_BYTE = 0; static final int DIGESTER_TYPE_STRING = 1; private final int digesterType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private DigesterConfig config = null; private boolean iterationsSet = false; private Integer iterations = null; private boolean invertPositionOfPlainSaltInEncryptionResultsSet = false; private Boolean invertPositionOfPlainSaltInEncryptionResults = null; private boolean invertPositionOfSaltInMessageBeforeDigestingSet = false; private Boolean invertPositionOfSaltInMessageBeforeDigesting = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean saltSizeBytesSet = false; private Integer saltSizeBytes = null; private boolean useLenientSaltSizeCheckSet = false; private Boolean useLenientSaltSizeCheck = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; private boolean unicodeNormalizationIgnoredSet = false; private Boolean unicodeNormalizationIgnored = null; private boolean prefixSet = false; private String prefix = null; private boolean suffixSet = false; private String suffix = null; public DigesterFactoryBean(final int encryptorType) { super(); this.digesterType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final DigesterConfig config) { this.config = config; this.configSet = true; } public void setIterations(final Integer iterations) { this.iterations = iterations; this.iterationsSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setInvertPositionOfPlainSaltInEncryptionResults( final Boolean invertPositionOfPlainSaltInEncryptionResults) { this.invertPositionOfPlainSaltInEncryptionResults = invertPositionOfPlainSaltInEncryptionResults; this.invertPositionOfPlainSaltInEncryptionResultsSet = true; } public void setInvertPositionOfSaltInMessageBeforeDigesting( final Boolean invertPositionOfSaltInMessageBeforeDigesting) { this.invertPositionOfSaltInMessageBeforeDigesting = invertPositionOfSaltInMessageBeforeDigesting; this.invertPositionOfSaltInMessageBeforeDigestingSet = true; } public void setSaltSizeBytes(final Integer saltSizeBytes) { this.saltSizeBytes = saltSizeBytes; this.saltSizeBytesSet = true; } public void setUseLenientSaltSizeCheck(final Boolean useLenientSaltSizeCheck) { this.useLenientSaltSizeCheck = useLenientSaltSizeCheck; this.useLenientSaltSizeCheckSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public void setUnicodeNormalizationIgnored(final Boolean unicodeNormalizationIgnored) { this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; this.unicodeNormalizationIgnoredSet = true; } public void setPrefix(final String prefix) { this.prefix = prefix; this.prefixSet = true; } public void setSuffix(final String suffix) { this.suffix = suffix; this.suffixSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private synchronized Object computeObject() throws Exception { Object digester = null; if (isPooled()) { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new PooledByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new PooledStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( digester, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new StandardByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new StandardStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } if (this.algorithmSet) { final Statement st = new Statement( digester, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( digester, "setConfig", new Object[] { this.config }); st.execute(); } if (this.iterationsSet && this.iterations != null) { final Statement st = new Statement( digester, "setIterations", new Object[] { this.iterations }); st.execute(); } if (this.invertPositionOfSaltInMessageBeforeDigestingSet && this.invertPositionOfSaltInMessageBeforeDigesting != null) { final Statement st = new Statement( digester, "setInvertPositionOfSaltInMessageBeforeDigesting", new Object[] { this.invertPositionOfSaltInMessageBeforeDigesting }); st.execute(); } if (this.invertPositionOfPlainSaltInEncryptionResultsSet && this.invertPositionOfPlainSaltInEncryptionResults != null) { final Statement st = new Statement( digester, "setInvertPositionOfPlainSaltInEncryptionResults", new Object[] { this.invertPositionOfPlainSaltInEncryptionResults }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( digester, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( digester, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( digester, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.saltSizeBytesSet && this.saltSizeBytes != null) { final Statement st = new Statement( digester, "setSaltSizeBytes", new Object[] { this.saltSizeBytes }); st.execute(); } if (this.useLenientSaltSizeCheckSet && this.useLenientSaltSizeCheck != null) { final Statement st = new Statement( digester, "setUseLenientSaltSizeCheck", new Object[] { this.useLenientSaltSizeCheck }); st.execute(); } if (digester instanceof StringDigester) { if (this.stringOutputTypeSet) { final Statement st = new Statement( digester, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } if (this.unicodeNormalizationIgnoredSet) { final Statement st = new Statement( digester, "setUnicodeNormalizationIgnored", new Object[] { this.unicodeNormalizationIgnored }); st.execute(); } if (this.prefixSet) { final Statement st = new Statement( digester, "setPrefix", new Object[] { this.prefix }); st.execute(); } if (this.suffixSet) { final Statement st = new Statement( digester, "setSuffix", new Object[] { this.suffix }); st.execute(); } } return digester; } public Class getObjectType() { if (this.digesterType == DIGESTER_TYPE_BYTE) { return ByteDigester.class; } else if (this.digesterType == DIGESTER_TYPE_STRING) { return StringDigester.class; } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } EncryptablePropertiesBeanDefinitionParser.java000066400000000000000000000052431360667575700416400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.util.Properties; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertiesBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertiesBeanDefinitionParser() { super(); } @Override protected boolean isEligibleAttribute(final String attributeName) { return super.isEligibleAttribute(attributeName) && !SCOPE_ATTRIBUTE.equals(attributeName) && !ENCRYPTOR_ATTRIBUTE.equals(attributeName); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertiesFactoryBean.class; } @Override protected void doParse(final Element element, final ParserContext parserContext, final BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); Properties parsedProps = parserContext.getDelegate().parsePropsElement(element); builder.addPropertyValue("properties", parsedProps); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addPropertyReference("encryptor", encryptorBeanName); } } } EncryptablePropertiesFactoryBean.java000066400000000000000000000075231360667575700400050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.io.IOException; import java.util.Properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.EncryptableProperties; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.support.PropertiesLoaderSupport; /** *

* Factory bean for creating encrptable properties objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptablePropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean, InitializingBean { private boolean singleton = true; private Properties singletonInstance; private Object encryptor = null; public EncryptablePropertiesFactoryBean() { super(); } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setEncryptor(final Object encryptor) { this.encryptor = encryptor; } public final void afterPropertiesSet() throws IOException { if (this.singleton) { this.singletonInstance = processEncryptable(mergeProperties()); } } public final Object getObject() throws IOException { if (this.singleton) { return this.singletonInstance; } return processEncryptable(mergeProperties()); } public Class getObjectType() { return EncryptableProperties.class; } private EncryptableProperties processEncryptable(final Properties props) { if (this.encryptor == null) { throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition cannot be null"); } if (this.encryptor instanceof TextEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((TextEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } else if (this.encryptor instanceof StringEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((StringEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition must be either " + "an org.jasypt.util.text.TextEncryptor or an org.jasypt.encryption.StringEncryptor " + "object. An object of class " + this.encryptor.getClass().getName() + " has been " + "specified instead."); } } EncryptablePropertyOverrideBeanDefinitionParser.java000066400000000000000000000041251360667575700430260ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.jasypt.spring31.properties.EncryptablePropertyOverrideConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertyOverrideBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertyOverrideBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertyOverrideConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreInvalidKeys", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptablePropertyPlaceholderBeanDefinitionParser.java000066400000000000000000000066041360667575700434750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer; import org.jasypt.spring31.properties.EncryptablePropertySourcesPlaceholderConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptablePropertyPlaceholderBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String SYSTEM_PROPERTIES_MODE_ATTRIBUTE = "system-properties-mode"; private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; private static final String SYSTEM_PROPERTIES_MODE_DEFAULT = "ENVIRONMENT"; EncryptablePropertyPlaceholderBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { // As of Spring 3.1, the default value of system-properties-mode has changed from // 'FALLBACK' to 'ENVIRONMENT'. This latter value indicates that resolution of // placeholders against system properties is a function of the Environment and // its current set of PropertySources if (element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE).equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { return EncryptablePropertySourcesPlaceholderConfigurer.class; } // the user has explicitly specified a value for system-properties-mode. Revert // to PropertyPlaceholderConfigurer to ensure backward compatibility. return EncryptablePropertyPlaceholderConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); String systemPropertiesModeName = element.getAttribute("system-properties-mode"); if (StringUtils.hasLength(systemPropertiesModeName) && !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptionNamespaceHandler.java000066400000000000000000000205221360667575700366010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** *

* Namespace handler for jasypt's encryption namespace. *

*

* In order to use this namespace, add its XML schema declaration to your Spring * beans file like: *

* * <beans xmlns="http://www.springframework.org/schema/beans"
*        ...
*        xmlns:encryption="http://www.jasypt.org/schema/encryption"
*        ...
*        xsi:schemaLocation="http://www.springframework.org/schema/beans
*                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
*                            ...
*                            http://www.jasypt.org/schema/encryption
*                            http://www.jasypt.org/schema/encryption/jasypt-spring31-encryption-1.xsd
*                            ..."> *
*

* This namespace offers the following elements for creating instances of specific jasypt artifacts * and add them to the Spring application context: *

*
    *
  • Digesters *
      *
    • {@link org.jasypt.digest.config.DigesterConfig} (simple, string, environment): <encryption:digester-config/>
    • *
    • {@link org.jasypt.digest.ByteDigester} (pooled or standard, depending on selected pool size): <encryption:byte-digester/>
    • *
    • {@link org.jasypt.digest.StringDigester} (pooled or standard, depending on selected pool size): <encryption:string-digester/>
    • *
    • Util digester classes: *
        *
      • {@link org.jasypt.util.password.BasicPasswordEncryptor}: <encryption:basic-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.StrongPasswordEncryptor}: <encryption:strong-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.ConfigurablePasswordEncryptor}: <encryption:configurable-password-encryptor/>
      • *
      *
    • *
    *
  • *
  • PBE Encryption *
      *
    • {@link org.jasypt.encryption.pbe.config.PBEConfig} (simple, string, environment): <encryption:encryptor-config/>
    • *
    • {@link org.jasypt.encryption.ByteEncryptor} (pooled or standard, depending on selected pool size): <encryption:byte-encryptor/>
    • *
    • {@link org.jasypt.encryption.StringEncryptor} (pooled or standard, depending on selected pool size): <encryption:string-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigIntegerEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-integer-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigDecimalEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-decimal-encryptor/>
    • *
    • Util encryptor classes: *
        *
      • {@link org.jasypt.util.text.BasicTextEncryptor}: <encryption:basic-text-encryptor/>
      • *
      • {@link org.jasypt.util.text.StrongTextEncryptor}: <encryption:strong-text-encryptor/>
      • *
      *
    • *
    *
  • *
  • Properties management *
      *
    • {@link org.jasypt.properties.EncryptableProperties} (equivalent to <util:properties/> adding property decryption): <encryption:encryptable-properties/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer} (equivalent to <context:property-placeholder/> adding property decryption): <encryption:encryptable-property-placeholder/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyOverrideConfigurer} (equivalent to <context:property-override/> adding property decryption): <encryption:encryptable-property-override/>
    • *
    *
  • *
* * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptionNamespaceHandler extends NamespaceHandlerSupport { public EncryptionNamespaceHandler() { super(); } public void init() { registerBeanDefinitionParser("encryptor-config", new EncryptorConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BYTE)); registerBeanDefinitionParser("string-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_STRING)); registerBeanDefinitionParser("big-decimal-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_DECIMAL)); registerBeanDefinitionParser("big-integer-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_INTEGER)); registerBeanDefinitionParser("basic-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("digester-config", new DigesterConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_BYTE)); registerBeanDefinitionParser("string-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_STRING)); registerBeanDefinitionParser("basic-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("configurable-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_CONFIGURABLE)); registerBeanDefinitionParser("encryptable-properties", new EncryptablePropertiesBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-placeholder", new EncryptablePropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-override", new EncryptablePropertyOverrideBeanDefinitionParser()); } } EncryptorBeanDefinitionParser.java000066400000000000000000000067421360667575700373050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private final int encryptorType; EncryptorBeanDefinitionParser(final int encryptorType) { super(); this.encryptorType = encryptorType; } @Override protected Class getBeanClass(final Element element) { return EncryptorFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.encryptorType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } EncryptorConfigBeanDefinitionParser.java000066400000000000000000000274221360667575700404310ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.encryption.pbe.config.EnvironmentPBEConfig; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; import org.jasypt.encryption.pbe.config.SimplePBEConfig; import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class EncryptorConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_IV_GENERATOR_CLASS_NAME = "iv-generator-class-name"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_KEY_OBTENTION_ITERATIONS, PARAM_PASSWORD, PARAM_POOL_SIZE, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_IV_GENERATOR_BEAN, PARAM_IV_GENERATOR_CLASS_NAME })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME = "key-obtention-iterations-env-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME = "key-obtention-iterations-sys-property-name"; private static final String PARAM_PASSWORD_ENV_NAME = "password-env-name"; private static final String PARAM_PASSWORD_SYS_PROPERTY_NAME = "password-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME = "iv-generator-class-name-env-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "iv-generator-class-name-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, PARAM_PASSWORD_ENV_NAME, PARAM_PASSWORD_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME })); EncryptorConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME, "ivGeneratorClassName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, "keyObtentionIterationsEnvName"); processStringAttribute(element, builder, PARAM_PASSWORD_ENV_NAME, "passwordEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, "ivGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, "keyObtentionIterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_PASSWORD_SYS_PROPERTY_NAME, "passwordSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "ivGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringPBEConfig.class; } if (isEnvironmentConfig) { return EnvironmentPBEConfig.class; } if (isStringConfig) { return SimpleStringPBEConfig.class; } return SimplePBEConfig.class; } } EncryptorFactoryBean.java000066400000000000000000000256501360667575700354460ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PooledPBEByteEncryptor; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating encryptor objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.0 * * @author Daniel Fernández * */ public final class EncryptorFactoryBean implements FactoryBean, InitializingBean { static final int ENCRYPTOR_TYPE_BYTE = 0; static final int ENCRYPTOR_TYPE_STRING = 1; static final int ENCRYPTOR_TYPE_BIG_DECIMAL = 2; static final int ENCRYPTOR_TYPE_BIG_INTEGER = 3; private final int encryptorType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private PBEConfig config = null; private boolean keyObtentionIterationsSet = false; private Integer keyObtentionIterations = null; private boolean passwordSet = false; private String password = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean ivGeneratorSet = false; private IvGenerator ivGenerator = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; public EncryptorFactoryBean(final int encryptorType) { super(); this.encryptorType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final PBEConfig config) { this.config = config; this.configSet = true; } public void setKeyObtentionIterations(final Integer keyObtentionIterations) { this.keyObtentionIterations = keyObtentionIterations; this.keyObtentionIterationsSet = true; } public void setPassword(final String password) { this.password = password; this.passwordSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setIvGenerator(final IvGenerator ivGenerator) { this.ivGenerator = ivGenerator; this.ivGeneratorSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private Object computeObject() throws Exception { Object encryptor = null; if (isPooled()) { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new PooledPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new PooledPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new PooledPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new PooledPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( encryptor, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new StandardPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new StandardPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new StandardPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new StandardPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } if (this.algorithmSet) { final Statement st = new Statement( encryptor, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( encryptor, "setConfig", new Object[] { this.config }); st.execute(); } if (this.keyObtentionIterationsSet && this.keyObtentionIterations != null) { final Statement st = new Statement( encryptor, "setKeyObtentionIterations", new Object[] { this.keyObtentionIterations }); st.execute(); } if (this.passwordSet) { final Statement st = new Statement( encryptor, "setPassword", new Object[] { this.password }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( encryptor, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( encryptor, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( encryptor, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.ivGeneratorSet) { final Statement st = new Statement( encryptor, "setIvGenerator", new Object[] { this.ivGenerator }); st.execute(); } if (this.stringOutputTypeSet && encryptor instanceof PBEStringEncryptor) { final Statement st = new Statement( encryptor, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } return encryptor; } public Class getObjectType() { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { return PBEByteEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { return PBEStringEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { return PBEBigDecimalEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { return PBEBigIntegerEncryptor.class; } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } UtilDigesterBeanDefinitionParser.java000066400000000000000000000064021360667575700377150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.StrongPasswordEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class UtilDigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; static final int UTIL_TYPE_CONFIGURABLE = 2; private final int utilType; UtilDigesterBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_CONFIGURABLE) { return ConfigurablePasswordEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } UtilEncryptorBeanDefinitionParser.java000066400000000000000000000046071360667575700401410ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring31.xml.encryption; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.0 * * @author Daniel Fernández * */ final class UtilEncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_PASSWORD = "password"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; private final int utilType; UtilEncryptorBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicTextEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongTextEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_PASSWORD, "password"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } jasypt-spring31-encryption-1.xsd000066400000000000000000001260501360667575700365200ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/java/org/jasypt/spring31/xml/encryption jasypt-jasypt-1.9.3/jasypt-spring31/src/main/metainf/000077500000000000000000000000001360667575700225105ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/main/metainf/spring.handlers000066400000000000000000000001471360667575700255360ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption=org.jasypt.spring31.xml.encryption.EncryptionNamespaceHandler jasypt-jasypt-1.9.3/jasypt-spring31/src/main/metainf/spring.schemas000066400000000000000000000002161360667575700253560ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption/jasypt-spring31-encryption-1.xsd=org/jasypt/spring31/xml/encryption/jasypt-spring31-encryption-1.xsd jasypt-jasypt-1.9.3/jasypt-spring31/src/test/000077500000000000000000000000001360667575700211205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/000077500000000000000000000000001360667575700220415ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/org/000077500000000000000000000000001360667575700226305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/org/jasypt/000077500000000000000000000000001360667575700241425ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/org/jasypt/spring31/000077500000000000000000000000001360667575700256105ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/org/jasypt/spring31/properties/000077500000000000000000000000001360667575700300045ustar00rootroot00000000000000EncryptablePropertyPlaceholderConfigurerTest.java000066400000000000000000000142621360667575700416410ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring31/src/test/java/org/jasypt/spring31/propertiespackage org.jasypt.spring31.properties; import junit.framework.TestCase; import java.util.HashMap; import java.util.Map; import org.jasypt.encryption.StringEncryptor; import org.jasypt.util.text.TextEncryptor; /* * ==Test resolveSystemProperty for encrypted env var== * * I don't have a great way to test the decryption of encrypted env var without requiring the test harness (surefire, IDE etc) * to have specified an encrypted environment variable. Here are a few options * - reflection hack to change the underlying system env map - * http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java. THis is what spring does to * test the propertyplaceholderconfigurer: * https://src.springframework.org/svn/spring-framework/trunk/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java * - extract the call to super.resolveSystemProperty(key) in resolveSystemProperty to a protected method and the test * will use a testspecifc subclass (http://xunitpatterns.com/Test-Specific%20Subclass.html) that overrides that method. * * However, i really don't think it is that big of a deal. The functionality responsible for getting system/env values * is defined in the super. All this class does is check to see if they have the encryption delimiters. I am pretty sure * I already went overboard on the test - ~100 lines of test for 3 lines of production code. * * User: carlos fernandez * Date: 6/28/11 * Time: 10:38 PM */ public class EncryptablePropertyPlaceholderConfigurerTest extends TestCase { //duplicated prefix suffix values in PropertyValueEncryptionUtils because PVEU constants are private private static final String ENCRYPTED_VALUE_PREFIX = "ENC("; private static final String ENCRYPTED_VALUE_SUFFIX = ")"; private String expectedDecryptedValue; private String encryptedValue; private String encryptedValueWithDelimiters; private String encryptedSysPropKey; private String unencryptedSysPropKey; private String unencryptedValue; public void setUp() { encryptedSysPropKey = "thisIsAnEncryptedSysPropertyKey"; encryptedValue = "encryptedString"; encryptedValueWithDelimiters = ENCRYPTED_VALUE_PREFIX + this.encryptedValue + ENCRYPTED_VALUE_SUFFIX; expectedDecryptedValue = "clearText"; System.setProperty(encryptedSysPropKey, encryptedValueWithDelimiters); unencryptedSysPropKey = "thisIsAnUNEncryptedSysPropertyKey"; unencryptedValue = "thisIsARegularString"; System.setProperty(unencryptedSysPropKey, unencryptedValue); } public void testConvertPropertyValueNotEncrypted() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, eppc.convertPropertyValue(unencryptedValue)); } public void testConvertPropertyValueDecryptWithStringEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testConvertPropertyValueDecryptWithTextEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, eppc.convertPropertyValue(encryptedValueWithDelimiters)); } public void testResolveSystemPropertyNullSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertNull(ppc.resolveSystemProperty("foofoofoo")); } public void testResolveSystemPropertyEncryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertEquals(expectedDecryptedValue, ppc.resolveSystemProperty(encryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithStringEncryptor(); assertEquals(unencryptedValue, ppc.resolveSystemProperty(unencryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedEnvVar() throws Exception { //the expectation is that the system has the HOME env var String unencryptedEnvVarKey = "HOME";//this is expected to exist on windows and unix systems String unencryptedEnvVarValue = System.getenv(unencryptedEnvVarKey); //lets make sure the env variable is set & is not null assertNotNull("no home env variable found", unencryptedEnvVarValue); EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); //allow ppc can check env vars ppc.setSearchSystemEnvironment(true); assertEquals(unencryptedEnvVarValue, ppc.resolveSystemProperty(unencryptedEnvVarKey)); } private EncryptablePropertyPlaceholderConfigurer createPPCWithTextEncryptor() { StubTextEncryptor textEncryptor = new StubTextEncryptor(); textEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(textEncryptor); } private EncryptablePropertyPlaceholderConfigurer createPPCWithStringEncryptor() { StubStringEncryptor stringEncryptor = new StubStringEncryptor(); stringEncryptor.addDecryption(encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(stringEncryptor); } abstract class StubEncryptor { private Map decryptMap = new HashMap(); public String decrypt(String encryptedMessage) { return (String)this.decryptMap.get(encryptedMessage); } public String encrypt(String message) { throw new UnsupportedOperationException(); } public void addDecryption(String encrypted, String expectedDecryption) { this.decryptMap.put(encrypted, expectedDecryption); } } class StubStringEncryptor extends StubEncryptor implements StringEncryptor{} class StubTextEncryptor extends StubEncryptor implements TextEncryptor{} } jasypt-jasypt-1.9.3/jasypt-spring4-testapp/000077500000000000000000000000001360667575700207505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/.gitignore000066400000000000000000000000721360667575700227370ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring4-testapp/pom.xml000066400000000000000000000222121360667575700222640ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring4-testapp war 201905 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD chuspicosvilar Chus Picos chuspicosvilar AT users.sourceforge.net Developer hokitorres Hoki Torres hokitorres AT users.sourceforge.net Developer sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone src/main/resources src/main/java **/*.properties **/*.xml **/*.html org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 org.apache.maven.plugins maven-resources-plugin 2.5 ISO-8859-1 org.jasypt jasypt 1.9.3-SNAPSHOT compile org.jasypt jasypt-spring4 1.9.3-SNAPSHOT compile javax.servlet servlet-api 2.5 provided org.springframework spring-core 4.0.0.RELEASE compile org.springframework spring-context 4.0.0.RELEASE compile org.springframework spring-beans 4.0.0.RELEASE compile org.springframework spring-aop 4.0.0.RELEASE compile org.springframework spring-aspects 4.0.0.RELEASE compile org.springframework spring-expression 4.0.0.RELEASE compile org.springframework spring-web 4.0.0.RELEASE compile org.springframework spring-webmvc 4.0.0.RELEASE compile javax.validation validation-api 1.0.0.GA compile org.hibernate hibernate-validator-annotation-processor 4.1.0.Final org.slf4j slf4j-api 1.6.1 compile org.slf4j slf4j-log4j12 1.6.1 compile log4j log4j 1.2.15 compile com.sun.jdmk jmxtools com.sun.jmx jmxri javax.jms jms javax.servlet jsp-api 2.0 provided javax.servlet jstl 1.1.2 compile taglibs standard 1.1.2 compile jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/000077500000000000000000000000001360667575700215375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/000077500000000000000000000000001360667575700224635ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/000077500000000000000000000000001360667575700234045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/000077500000000000000000000000001360667575700241735ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/jasypt/000077500000000000000000000000001360667575700255055ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/jasypt/spring4testapp/000077500000000000000000000000001360667575700304745ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/jasypt/spring4testapp/web/000077500000000000000000000000001360667575700312515ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/jasypt/spring4testapp/web/controller/000077500000000000000000000000001360667575700334345ustar00rootroot00000000000000Index.java000066400000000000000000000133331360667575700352720ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/java/org/jasypt/spring4testapp/web/controller/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4testapp.web.controller; import java.util.Properties; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.StringDigester; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class Index { @Autowired private PBEByteEncryptor enc1; @Autowired private PBEBigDecimalEncryptor enc3; @Autowired private PBEBigIntegerEncryptor enc4; @Autowired private PBEStringEncryptor encAES; @Autowired private BasicTextEncryptor bte; @Autowired private StrongTextEncryptor ste; @Autowired private StringDigester sd; @Autowired private ByteDigester bd; @Autowired private PasswordEncryptor bpe; @Autowired @Qualifier("eprop1") private Properties eprop1; @Autowired private ApplicationContext appCtx; @Autowired @Qualifier("eprop2") private Properties eprop2; @Value("${city.name}") private String cityName; @Value("${country.name}") private String countryName; public Index() { super(); } @RequestMapping({"/"}) public String show(final ModelMap model) { final byte[] mba = "Hello!".getBytes(); final byte[] encMba = this.enc1.encrypt(mba); model.addAttribute("encMba", new String(encMba) + " | " + this.enc1.getClass().getName()); final StandardPBEStringEncryptor enctest = new StandardPBEStringEncryptor(); enctest.setPassword("jasypt"); enctest.setAlgorithm("PBEWithMD5AndTripleDES"); enctest.setStringOutputType("hexa"); enctest.setKeyObtentionIterations(20); System.out.println("BigDecimal: " + enc3.getClass().getName()); System.out.println("BigInteger: " + enc4.getClass().getName()); System.out.println(this.enc3.getClass().getName()); System.out.println(this.enc4.getClass().getName()); String bteE = bte.encrypt("hello!"); System.out.println("Basic encryptor: " + bte.getClass().getName() + bteE + " -> " + bte.decrypt(bteE)); String steE = ste.encrypt("hello!"); System.out.println("Strong encryptor: " + ste.getClass().getName() + steE + " -> " + ste.decrypt(steE)); String encAESe = encAES.encrypt("hello!"); System.out.println("AES: " + encAES.getClass().getName() + encAESe + " -> " + encAES.decrypt(encAESe)); model.addAttribute("encAES", new String(encAESe) + " | " + encAES.getClass().getName()); System.out.println(this.sd.digest("myPassword") + " | " + this.sd.getClass().getName()); System.out.println(new String(this.bd.digest(mba)) + " | " + this.bd.getClass().getName()); final String ep = this.bpe.encryptPassword("HELLO!!"); System.out.println(ep + " | " + this.bpe.getClass().getName()); final ConfigurablePasswordEncryptor configurablePasswordEncryptor = new ConfigurablePasswordEncryptor(); configurablePasswordEncryptor.setAlgorithm("SHA-1"); configurablePasswordEncryptor.setStringOutputType("0x"); System.out.println(configurablePasswordEncryptor.checkPassword("HELLO!!", ep)); System.out.println(this.eprop1); System.out.println(this.eprop2); System.out.println("----------"); System.out.println(this.eprop1.getProperty("prop1")); System.out.println(this.eprop1.getProperty("prop2")); System.out.println("Existing digester: " + System.identityHashCode(this.sd)); StringDigester stex = (StringDigester) this.appCtx.getBean("sd1"); System.out.println("First digester: " + System.identityHashCode(stex)); stex = (StringDigester) this.appCtx.getBean("sd1"); System.out.println("Second digester: " + System.identityHashCode(stex)); System.out.println("City name: " + this.cityName); System.out.println("Country name: " + this.countryName); return "index"; } } jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/resources/000077500000000000000000000000001360667575700244755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/resources/log4j.properties000066400000000000000000000004061360667575700276320ustar00rootroot00000000000000log4j.rootLogger = WARN, stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p [%c{1}] (%F:%L) - %m%n jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/resources/some.properties000066400000000000000000000001141360667575700275520ustar00rootroot00000000000000country.name=ENC(zl94ORjq8JUSN/c5xGgVxomrMd5bf9K4) city.name=Penguin City jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/000077500000000000000000000000001360667575700237415ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/META-INF/000077500000000000000000000000001360667575700251015ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/META-INF/MANIFEST.MF000066400000000000000000000000471360667575700265340ustar00rootroot00000000000000Manifest-Version: 1.0 Class-Path: jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/WEB-INF/000077500000000000000000000000001360667575700247705ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/WEB-INF/spring-servlet.xml000066400000000000000000000113201360667575700304730ustar00rootroot00000000000000 something ENC(JhuIj9BJvw7nEix0n4oM/VG0kgOTK51p4E1vzEWn65Nc7y8EfLomhCStYBNSyR4J) something-two jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/WEB-INF/templates/000077500000000000000000000000001360667575700267665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/WEB-INF/templates/index.jsp000066400000000000000000000013521360667575700306140ustar00rootroot00000000000000<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %><%@ taglib prefix="s" uri="http://www.springframework.org/tags" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Jasypt Spring4 Test Application

This is a JSP

jasypt-jasypt-1.9.3/jasypt-spring4-testapp/src/main/webapp/WEB-INF/web.xml000066400000000000000000000015731360667575700262750ustar00rootroot00000000000000 jasypt-spring4-testapp 60 spring org.springframework.web.servlet.DispatcherServlet 1 spring / index jasypt-jasypt-1.9.3/jasypt-spring4/000077500000000000000000000000001360667575700172725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/.gitignore000066400000000000000000000000721360667575700212610ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-spring4/BUILD.txt000066400000000000000000000015111360667575700206700ustar00rootroot00000000000000 Building JASYPT-SPRING4 ----------------------- To build JASYPT-SPRING4 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRING4 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-spring4-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-spring4/{version}/jasypt-spring4-{version}.jar Generating Javadoc for JASYPT-SPRING4 ------------------------------------- If you wish to generate the javadoc for JASYPT-SPRING4, execute this from the JASYPT-SPRING4 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-spring4/ChangeLog.txt000066400000000000000000000001171360667575700216610ustar00rootroot000000000000001.9.3 ===== - Created new jasypt-spring4 module for Spring 4 integration. jasypt-jasypt-1.9.3/jasypt-spring4/LICENSE.txt000066400000000000000000000264501360667575700211240ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-spring4/NOTICE.txt000066400000000000000000000074211360667575700210200ustar00rootroot00000000000000 Copyright (c) 2007-2017, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-spring4/README.txt000066400000000000000000000006261360667575700207740ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-spring4/RELEASING.txt000066400000000000000000000023501360667575700213440ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-spring4/USAGE.txt000066400000000000000000000012161360667575700206770ustar00rootroot00000000000000 Using JASYPT-SPRING4 from Maven 2 --------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-spring4 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-spring4/pom.xml000066400000000000000000000171151360667575700206140ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-spring4 1.9.3 jar JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD chuspicosvilar Chus Picos chuspicosvilar AT users.sourceforge.net Developer hokitorres Hoki Torres hokitorres AT users.sourceforge.net Developer sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true org.springframework.maven.milestone Maven Central Compatible Spring Milestone Repository http://maven.springframework.org/milestone true src/main/java **/*.xsd src/main/resources . META-INF LICENSE.txt NOTICE.txt src/main/metainf META-INF spring.handlers spring.schemas src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework spring-core 4.0.0.RELEASE provided true org.springframework spring-beans 4.0.0.RELEASE provided true org.springframework spring-web 4.0.0.RELEASE provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-spring4/src/000077500000000000000000000000001360667575700200615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/000077500000000000000000000000001360667575700210055ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/000077500000000000000000000000001360667575700217265ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/000077500000000000000000000000001360667575700225155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/000077500000000000000000000000001360667575700240275ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/000077500000000000000000000000001360667575700254155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/000077500000000000000000000000001360667575700276115ustar00rootroot00000000000000EncryptablePreferencesPlaceholderConfigurer.java000066400000000000000000000111431360667575700412160ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.properties; import java.util.Properties; import java.util.prefs.Preferences; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt preferences values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

ENC(!"DGAS24FaIO$)
*

* * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePreferencesPlaceholderConfigurer extends PreferencesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePreferencesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePreferencesPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePreferencesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.util.Properties) */ @Override protected String resolvePlaceholder(final String placeholder, final Properties props) { final String result = super.resolvePlaceholder(placeholder, props); return convertPropertyValue(result); } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer#resolvePlaceholder(java.lang.String, java.lang.String, java.util.prefs.Preferences) */ @Override protected String resolvePlaceholder( final String path, final String key, final Preferences preferences) { final String result = super.resolvePlaceholder(path, key, preferences); return convertPropertyValue(result); } } EncryptablePropertiesPropertySource.java000066400000000000000000000057651360667575700376650ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.properties; import java.util.Properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.EncryptableProperties; import org.jasypt.util.text.TextEncryptor; import org.springframework.core.env.PropertiesPropertySource; /** * * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePropertiesPropertySource extends PropertiesPropertySource { public EncryptablePropertiesPropertySource(final String name, final EncryptableProperties props) { super(name, props); } public EncryptablePropertiesPropertySource(final String name, final Properties props, final TextEncryptor encryptor) { super(name, processProperties(props, encryptor)); } public EncryptablePropertiesPropertySource(final String name, final Properties props, final StringEncryptor encryptor) { super(name, processProperties(props, encryptor)); } private static Properties processProperties(final Properties props, final TextEncryptor encryptor) { if (props == null) { return null; } if (props instanceof EncryptableProperties) { throw new IllegalArgumentException( "Properties object already is an " + EncryptableProperties.class.getName() + " object. No encryptor should be specified."); } final EncryptableProperties encryptableProperties = new EncryptableProperties(encryptor); encryptableProperties.putAll(props); return encryptableProperties; } private static Properties processProperties(final Properties props, final StringEncryptor encryptor) { if (props == null) { return null; } if (props instanceof EncryptableProperties) { throw new IllegalArgumentException( "Properties object already is an " + EncryptableProperties.class.getName() + " object. No encryptor should be specified."); } final EncryptableProperties encryptableProperties = new EncryptableProperties(encryptor); encryptableProperties.putAll(props); return encryptableProperties; } } EncryptablePropertyOverrideConfigurer.java000066400000000000000000000073111360667575700401400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyOverrideConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyOverrideConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePropertyOverrideConfigurer extends PropertyOverrideConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyOverrideConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyOverrideConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyOverrideConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyOverrideConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } EncryptablePropertyPlaceholderConfigurer.java000066400000000000000000000100531360667575700406000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; /** *

* Subclass of * org.springframework.beans.factory.config.PropertyPlaceholderConfigurer * which can make use of a {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the loaded resource locations. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

my.value=ENC(!"DGAS24FaIO$)
*

*

* Encrypted and unencrypted objects can be combined in the same resources file. *

* * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertyPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertyPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } /* * (non-Javadoc) * * @since 1.8 * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#resolveSystemProperty(java.lang.String) */ @Override protected String resolveSystemProperty(final String key) { return convertPropertyValue(super.resolveSystemProperty(key)); } } EncryptablePropertySourcesPlaceholderConfigurer.java000066400000000000000000000104641360667575700421520ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.properties; import java.io.IOException; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.jasypt.util.text.TextEncryptor; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; /** *

*

* * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer { /* * Only one of these instances will be initialized, the other one will be * null. */ private final StringEncryptor stringEncryptor; private final TextEncryptor textEncryptor; /* * This flag will keep track of whether the "convertProperties()" method * (which decrypts encrypted property entries) has already been called * or not. * * This is needed because of a bug in Spring 3.1.0.RELEASE: * https://jira.springsource.org/browse/SPR-8928 * * This flag will avoid calling "convertProperties()" twice once this * bug has been solved. */ private boolean alreadyConverted = false; /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance * which will use the passed {@link StringEncryptor} object to decrypt * encrypted values. *

* * @param stringEncryptor * the {@link StringEncryptor} to be used do decrypt values. It * can not be null. */ public EncryptablePropertySourcesPlaceholderConfigurer( final StringEncryptor stringEncryptor) { super(); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptablePropertyPlaceholderConfigurer instance which will use the * passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor * the {@link TextEncryptor} to be used do decrypt values. It can * not be null. */ public EncryptablePropertySourcesPlaceholderConfigurer(final TextEncryptor textEncryptor) { super(); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /* * This is needed because of https://jira.springsource.org/browse/SPR-8928 */ @Override protected Properties mergeProperties() throws IOException { final Properties mergedProperties = super.mergeProperties(); convertProperties(mergedProperties); return mergedProperties; } /* * This is needed because of https://jira.springsource.org/browse/SPR-8928 */ @Override protected void convertProperties(final Properties props) { if (!this.alreadyConverted) { super.convertProperties(props); this.alreadyConverted = true; } } /* * (non-Javadoc) * * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertPropertyValue(java.lang.String) */ @Override protected String convertPropertyValue(final String originalValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(originalValue)) { return originalValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(originalValue, this.stringEncryptor); } return PropertyValueEncryptionUtils.decrypt(originalValue, this.textEncryptor); } } jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/000077500000000000000000000000001360667575700262155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/000077500000000000000000000000001360667575700304075ustar00rootroot00000000000000AbstractEncryptablePropertyLoadingBeanDefinitionParser.java000066400000000000000000000054531360667575700441550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ abstract class AbstractEncryptablePropertyLoadingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptablePropertyLoadingBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateId() { return true; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { String location = element.getAttribute("location"); if (StringUtils.hasLength(location)) { String[] locations = StringUtils.commaDelimitedListToStringArray(location); builder.addPropertyValue("locations", locations); } String propertiesRef = element.getAttribute("properties-ref"); if (StringUtils.hasLength(propertiesRef)) { builder.addPropertyReference("properties", propertiesRef); } String fileEncoding = element.getAttribute("file-encoding"); if (StringUtils.hasLength(fileEncoding)) { builder.addPropertyReference("fileEncoding", fileEncoding); } String order = element.getAttribute("order"); if (StringUtils.hasLength(order)) { builder.addPropertyValue("order", Integer.valueOf(order)); } builder.addPropertyValue("ignoreResourceNotFound", Boolean.valueOf(element.getAttribute("ignore-resource-not-found"))); builder.addPropertyValue("localOverride", Boolean.valueOf(element.getAttribute("local-override"))); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); } } AbstractEncryptionBeanDefinitionParser.java000066400000000000000000000066041360667575700407730ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ abstract class AbstractEncryptionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected AbstractEncryptionBeanDefinitionParser() { super(); } @Override protected boolean shouldGenerateIdAsFallback() { return true; } protected final void processStringAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { builder.addPropertyValue(propertyName, attributeValue); } } protected final void processIntegerAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { try { final Integer attributeIntegerValue = Integer.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeIntegerValue); } catch (final NumberFormatException e) { throw new NumberFormatException( "Config attribute \"" + attributeName + "\" is not a valid integer"); } } } protected final void processBooleanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { final Boolean attributeBooleanValue = Boolean.valueOf(attributeValue); builder.addPropertyValue(propertyName, attributeBooleanValue); } } protected final void processBeanAttribute(final Element element, final BeanDefinitionBuilder builder, final String attributeName, final String propertyName) { final String beanName = element.getAttribute(attributeName); if (StringUtils.hasText(beanName)) { builder.addPropertyReference(propertyName, beanName); } } } DigesterBeanDefinitionParser.java000066400000000000000000000110641360667575700367170ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class DigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private final int digesterType; DigesterBeanDefinitionParser(final int digesterType) { super(); this.digesterType = digesterType; } @Override protected Class getBeanClass(final Element element) { return DigesterFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.digesterType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processBooleanAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } DigesterConfigBeanDefinitionParser.java000066400000000000000000000403171360667575700400500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.digest.config.EnvironmentDigesterConfig; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.digest.config.SimpleStringDigesterConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.3 * * @author Chus Picos * */ final class DigesterConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_ITERATIONS = "iterations"; private static final String PARAM_SALT_SIZE_BYTES = "salt-size-bytes"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invert-position-of-salt-in-message-before-digesting"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invert-position-of-plain-salt-in-encryption-results"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK = "use-lenient-salt-size-check"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_ITERATIONS, PARAM_SALT_SIZE_BYTES, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, PARAM_USE_LENIENT_SALT_SIZE_CHECK, PARAM_POOL_SIZE })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED = "unicode-normalization-ignored"; private static final String PARAM_PREFIX = "prefix"; private static final String PARAM_SUFFIX = "suffix"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE, PARAM_UNICODE_NORMALIZATION_IGNORED, PARAM_PREFIX, PARAM_SUFFIX })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_ITERATIONS_ENV_NAME = "iterations-env-name"; private static final String PARAM_ITERATIONS_SYS_PROPERTY_NAME = "iterations-sys-property-name"; private static final String PARAM_SALT_SIZE_BYTES_ENV_NAME = "salt-size-bytes-env-name"; private static final String PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME = "salt-size-bytes-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME = "invert-position-of-salt-in-message-before-digesting-env-name"; private static final String PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME = "invert-position-of-salt-in-message-before-digesting-sys-property-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME = "invert-position-of-plain-salt-in-encryption-results-env-name"; private static final String PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME = "invert-position-of-plain-salt-in-encryption-results-sys-property-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME = "use-lenient-salt-size-check-env-name"; private static final String PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME = "use-lenient-salt-size-check-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_ITERATIONS_ENV_NAME, PARAM_ITERATIONS_SYS_PROPERTY_NAME, PARAM_SALT_SIZE_BYTES_ENV_NAME, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME = "unicode-normalization-ignored-env-name"; private static final String PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME = "unicode-normalization-ignored-sys-property-name"; private static final String PARAM_PREFIX_ENV_NAME = "prefix-env-name"; private static final String PARAM_PREFIX_SYS_PROPERTY_NAME = "prefix-sys-property-name"; private static final String PARAM_SUFFIX_ENV_NAME = "suffix-env-name"; private static final String PARAM_SUFFIX_SYS_PROPERTY_NAME = "suffix-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, PARAM_PREFIX_ENV_NAME, PARAM_PREFIX_SYS_PROPERTY_NAME, PARAM_SUFFIX_ENV_NAME, PARAM_SUFFIX_SYS_PROPERTY_NAME })); DigesterConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_ITERATIONS, "iterations"); processIntegerAttribute(element, builder, PARAM_SALT_SIZE_BYTES, "saltSizeBytes"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING, "invertPositionOfSaltInMessageBeforeDigesting"); processBooleanAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS, "invertPositionOfPlainSaltInEncryptionResults"); processBooleanAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK, "useLenientSaltSizeCheck"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED, "unicodeNormalizationIgnored"); processStringAttribute(element, builder, PARAM_PREFIX, "prefix"); processStringAttribute(element, builder, PARAM_SUFFIX, "suffix"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_ITERATIONS_ENV_NAME, "iterationsEnvName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_ENV_NAME, "saltSizeBytesEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_ENV_NAME, "invertPositionOfSaltInMessageBeforeDigestingEnvName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_ENV_NAME, "invertPositionOfPlainSaltInEncryptionResultsEnvName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_ENV_NAME, "useLenientSaltSizeCheckEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_ITERATIONS_SYS_PROPERTY_NAME, "iterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_SIZE_BYTES_SYS_PROPERTY_NAME, "saltSizeBytesSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING_SYS_PROPERTY_NAME, "invertPositionOfSaltInMessageBeforeDigestingSysPropertyName"); processStringAttribute(element, builder, PARAM_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS_SYS_PROPERTY_NAME, "invertPositionOfPlainSaltInEncryptionResultsSysPropertyName"); processStringAttribute(element, builder, PARAM_USE_LENIENT_SALT_SIZE_CHECK_SYS_PROPERTY_NAME, "useLenientSaltSizeCheckSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_ENV_NAME, "unicodeNormalizationIgnoredEnvName"); processStringAttribute(element, builder, PARAM_UNICODE_NORMALIZATION_IGNORED_SYS_PROPERTY_NAME, "unicodeNormalizationIgnoredSysPropertyName"); processStringAttribute(element, builder, PARAM_PREFIX_ENV_NAME, "prefixEnvName"); processStringAttribute(element, builder, PARAM_PREFIX_SYS_PROPERTY_NAME, "prefixSysPropertyName"); processStringAttribute(element, builder, PARAM_SUFFIX_ENV_NAME, "suffixEnvName"); processStringAttribute(element, builder, PARAM_SUFFIX_SYS_PROPERTY_NAME, "suffixSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringDigesterConfig.class; } if (isEnvironmentConfig) { return EnvironmentDigesterConfig.class; } if (isStringConfig) { return SimpleStringDigesterConfig.class; } return SimpleDigesterConfig.class; } } DigesterFactoryBean.java000066400000000000000000000323061360667575700350630ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.digest.ByteDigester; import org.jasypt.digest.PooledByteDigester; import org.jasypt.digest.PooledStringDigester; import org.jasypt.digest.StandardByteDigester; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.StringDigester; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating digester objects from the encryption namespace * elements. Do not use directly. *

* * @since 1.9.3 * * @author Chus Picos * */ public final class DigesterFactoryBean implements FactoryBean, InitializingBean { static final int DIGESTER_TYPE_BYTE = 0; static final int DIGESTER_TYPE_STRING = 1; private final int digesterType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private DigesterConfig config = null; private boolean iterationsSet = false; private Integer iterations = null; private boolean invertPositionOfPlainSaltInEncryptionResultsSet = false; private Boolean invertPositionOfPlainSaltInEncryptionResults = null; private boolean invertPositionOfSaltInMessageBeforeDigestingSet = false; private Boolean invertPositionOfSaltInMessageBeforeDigesting = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean saltSizeBytesSet = false; private Integer saltSizeBytes = null; private boolean useLenientSaltSizeCheckSet = false; private Boolean useLenientSaltSizeCheck = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; private boolean unicodeNormalizationIgnoredSet = false; private Boolean unicodeNormalizationIgnored = null; private boolean prefixSet = false; private String prefix = null; private boolean suffixSet = false; private String suffix = null; public DigesterFactoryBean(final int encryptorType) { super(); this.digesterType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final DigesterConfig config) { this.config = config; this.configSet = true; } public void setIterations(final Integer iterations) { this.iterations = iterations; this.iterationsSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setInvertPositionOfPlainSaltInEncryptionResults( final Boolean invertPositionOfPlainSaltInEncryptionResults) { this.invertPositionOfPlainSaltInEncryptionResults = invertPositionOfPlainSaltInEncryptionResults; this.invertPositionOfPlainSaltInEncryptionResultsSet = true; } public void setInvertPositionOfSaltInMessageBeforeDigesting( final Boolean invertPositionOfSaltInMessageBeforeDigesting) { this.invertPositionOfSaltInMessageBeforeDigesting = invertPositionOfSaltInMessageBeforeDigesting; this.invertPositionOfSaltInMessageBeforeDigestingSet = true; } public void setSaltSizeBytes(final Integer saltSizeBytes) { this.saltSizeBytes = saltSizeBytes; this.saltSizeBytesSet = true; } public void setUseLenientSaltSizeCheck(final Boolean useLenientSaltSizeCheck) { this.useLenientSaltSizeCheck = useLenientSaltSizeCheck; this.useLenientSaltSizeCheckSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public void setUnicodeNormalizationIgnored(final Boolean unicodeNormalizationIgnored) { this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; this.unicodeNormalizationIgnoredSet = true; } public void setPrefix(final String prefix) { this.prefix = prefix; this.prefixSet = true; } public void setSuffix(final String suffix) { this.suffix = suffix; this.suffixSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private synchronized Object computeObject() throws Exception { Object digester = null; if (isPooled()) { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new PooledByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new PooledStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( digester, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.digesterType == DIGESTER_TYPE_BYTE) { digester = new StandardByteDigester(); } else if (this.digesterType == DIGESTER_TYPE_STRING) { digester = new StandardStringDigester(); } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } if (this.algorithmSet) { final Statement st = new Statement( digester, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( digester, "setConfig", new Object[] { this.config }); st.execute(); } if (this.iterationsSet && this.iterations != null) { final Statement st = new Statement( digester, "setIterations", new Object[] { this.iterations }); st.execute(); } if (this.invertPositionOfSaltInMessageBeforeDigestingSet && this.invertPositionOfSaltInMessageBeforeDigesting != null) { final Statement st = new Statement( digester, "setInvertPositionOfSaltInMessageBeforeDigesting", new Object[] { this.invertPositionOfSaltInMessageBeforeDigesting }); st.execute(); } if (this.invertPositionOfPlainSaltInEncryptionResultsSet && this.invertPositionOfPlainSaltInEncryptionResults != null) { final Statement st = new Statement( digester, "setInvertPositionOfPlainSaltInEncryptionResults", new Object[] { this.invertPositionOfPlainSaltInEncryptionResults }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( digester, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( digester, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( digester, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.saltSizeBytesSet && this.saltSizeBytes != null) { final Statement st = new Statement( digester, "setSaltSizeBytes", new Object[] { this.saltSizeBytes }); st.execute(); } if (this.useLenientSaltSizeCheckSet && this.useLenientSaltSizeCheck != null) { final Statement st = new Statement( digester, "setUseLenientSaltSizeCheck", new Object[] { this.useLenientSaltSizeCheck }); st.execute(); } if (digester instanceof StringDigester) { if (this.stringOutputTypeSet) { final Statement st = new Statement( digester, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } if (this.unicodeNormalizationIgnoredSet) { final Statement st = new Statement( digester, "setUnicodeNormalizationIgnored", new Object[] { this.unicodeNormalizationIgnored }); st.execute(); } if (this.prefixSet) { final Statement st = new Statement( digester, "setPrefix", new Object[] { this.prefix }); st.execute(); } if (this.suffixSet) { final Statement st = new Statement( digester, "setSuffix", new Object[] { this.suffix }); st.execute(); } } return digester; } public Class getObjectType() { if (this.digesterType == DIGESTER_TYPE_BYTE) { return ByteDigester.class; } else if (this.digesterType == DIGESTER_TYPE_STRING) { return StringDigester.class; } else { throw new IllegalArgumentException("Unknown digester type: " + this.digesterType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } EncryptablePropertiesBeanDefinitionParser.java000066400000000000000000000052251360667575700415000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.util.Properties; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class EncryptablePropertiesBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertiesBeanDefinitionParser() { super(); } @Override protected boolean isEligibleAttribute(final String attributeName) { return super.isEligibleAttribute(attributeName) && !SCOPE_ATTRIBUTE.equals(attributeName) && !ENCRYPTOR_ATTRIBUTE.equals(attributeName); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertiesFactoryBean.class; } @Override protected void doParse(final Element element, final ParserContext parserContext, final BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); Properties parsedProps = parserContext.getDelegate().parsePropsElement(element); builder.addPropertyValue("properties", parsedProps); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addPropertyReference("encryptor", encryptorBeanName); } } } EncryptablePropertiesFactoryBean.java000066400000000000000000000075051360667575700376450ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.io.IOException; import java.util.Properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.properties.EncryptableProperties; import org.jasypt.util.text.TextEncryptor; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.support.PropertiesLoaderSupport; /** *

* Factory bean for creating encrptable properties objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptablePropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean, InitializingBean { private boolean singleton = true; private Properties singletonInstance; private Object encryptor = null; public EncryptablePropertiesFactoryBean() { super(); } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setEncryptor(final Object encryptor) { this.encryptor = encryptor; } public final void afterPropertiesSet() throws IOException { if (this.singleton) { this.singletonInstance = processEncryptable(mergeProperties()); } } public final Object getObject() throws IOException { if (this.singleton) { return this.singletonInstance; } return processEncryptable(mergeProperties()); } public Class getObjectType() { return EncryptableProperties.class; } private EncryptableProperties processEncryptable(final Properties props) { if (this.encryptor == null) { throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition cannot be null"); } if (this.encryptor instanceof TextEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((TextEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } else if (this.encryptor instanceof StringEncryptor) { final EncryptableProperties encryptableProperties = new EncryptableProperties((StringEncryptor)this.encryptor); encryptableProperties.putAll(props); return encryptableProperties; } throw new IllegalArgumentException( "\"encryptor\" property in EncryptableProperties definition must be either " + "an org.jasypt.util.text.TextEncryptor or an org.jasypt.encryption.StringEncryptor " + "object. An object of class " + this.encryptor.getClass().getName() + " has been " + "specified instead."); } } EncryptablePropertyOverrideBeanDefinitionParser.java000066400000000000000000000041061360667575700426650ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.jasypt.spring4.properties.EncryptablePropertyOverrideConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class EncryptablePropertyOverrideBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; EncryptablePropertyOverrideBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return EncryptablePropertyOverrideConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreInvalidKeys", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptablePropertyPlaceholderBeanDefinitionParser.java000066400000000000000000000065641360667575700433420ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer; import org.jasypt.spring4.properties.EncryptablePropertySourcesPlaceholderConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class EncryptablePropertyPlaceholderBeanDefinitionParser extends AbstractEncryptablePropertyLoadingBeanDefinitionParser { private static final String SYSTEM_PROPERTIES_MODE_ATTRIBUTE = "system-properties-mode"; private static final String ENCRYPTOR_ATTRIBUTE = "encryptor"; private static final String SYSTEM_PROPERTIES_MODE_DEFAULT = "ENVIRONMENT"; EncryptablePropertyPlaceholderBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { // As of Spring 3.1, the default value of system-properties-mode has changed from // 'FALLBACK' to 'ENVIRONMENT'. This latter value indicates that resolution of // placeholders against system properties is a function of the Environment and // its current set of PropertySources if (element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE).equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { return EncryptablePropertySourcesPlaceholderConfigurer.class; } // the user has explicitly specified a value for system-properties-mode. Revert // to PropertyPlaceholderConfigurer to ensure backward compatibility. return EncryptablePropertyPlaceholderConfigurer.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { super.doParse(element, builder); builder.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); String systemPropertiesModeName = element.getAttribute("system-properties-mode"); if (StringUtils.hasLength(systemPropertiesModeName) && !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName); } final String encryptorBeanName = element.getAttribute(ENCRYPTOR_ATTRIBUTE); if (StringUtils.hasText(encryptorBeanName)) { builder.addConstructorArgReference(encryptorBeanName); } } } EncryptionNamespaceHandler.java000066400000000000000000000205031360667575700364400ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** *

* Namespace handler for jasypt's encryption namespace. *

*

* In order to use this namespace, add its XML schema declaration to your Spring * beans file like: *

* * <beans xmlns="http://www.springframework.org/schema/beans"
*        ...
*        xmlns:encryption="http://www.jasypt.org/schema/encryption"
*        ...
*        xsi:schemaLocation="http://www.springframework.org/schema/beans
*                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
*                            ...
*                            http://www.jasypt.org/schema/encryption
*                            http://www.jasypt.org/schema/encryption/jasypt-spring4-encryption-1.xsd
*                            ..."> *
*

* This namespace offers the following elements for creating instances of specific jasypt artifacts * and add them to the Spring application context: *

*
    *
  • Digesters *
      *
    • {@link org.jasypt.digest.config.DigesterConfig} (simple, string, environment): <encryption:digester-config/>
    • *
    • {@link org.jasypt.digest.ByteDigester} (pooled or standard, depending on selected pool size): <encryption:byte-digester/>
    • *
    • {@link org.jasypt.digest.StringDigester} (pooled or standard, depending on selected pool size): <encryption:string-digester/>
    • *
    • Util digester classes: *
        *
      • {@link org.jasypt.util.password.BasicPasswordEncryptor}: <encryption:basic-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.StrongPasswordEncryptor}: <encryption:strong-password-encryptor/>
      • *
      • {@link org.jasypt.util.password.ConfigurablePasswordEncryptor}: <encryption:configurable-password-encryptor/>
      • *
      *
    • *
    *
  • *
  • PBE Encryption *
      *
    • {@link org.jasypt.encryption.pbe.config.PBEConfig} (simple, string, environment): <encryption:encryptor-config/>
    • *
    • {@link org.jasypt.encryption.ByteEncryptor} (pooled or standard, depending on selected pool size): <encryption:byte-encryptor/>
    • *
    • {@link org.jasypt.encryption.StringEncryptor} (pooled or standard, depending on selected pool size): <encryption:string-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigIntegerEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-integer-encryptor/>
    • *
    • {@link org.jasypt.encryption.BigDecimalEncryptor} (pooled or standard, depending on selected pool size): <encryption:big-decimal-encryptor/>
    • *
    • Util encryptor classes: *
        *
      • {@link org.jasypt.util.text.BasicTextEncryptor}: <encryption:basic-text-encryptor/>
      • *
      • {@link org.jasypt.util.text.StrongTextEncryptor}: <encryption:strong-text-encryptor/>
      • *
      *
    • *
    *
  • *
  • Properties management *
      *
    • {@link org.jasypt.properties.EncryptableProperties} (equivalent to <util:properties/> adding property decryption): <encryption:encryptable-properties/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer} (equivalent to <context:property-placeholder/> adding property decryption): <encryption:encryptable-property-placeholder/>
    • *
    • {@link org.jasypt.spring3.properties.EncryptablePropertyOverrideConfigurer} (equivalent to <context:property-override/> adding property decryption): <encryption:encryptable-property-override/>
    • *
    *
  • *
* * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptionNamespaceHandler extends NamespaceHandlerSupport { public EncryptionNamespaceHandler() { super(); } public void init() { registerBeanDefinitionParser("encryptor-config", new EncryptorConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BYTE)); registerBeanDefinitionParser("string-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_STRING)); registerBeanDefinitionParser("big-decimal-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_DECIMAL)); registerBeanDefinitionParser("big-integer-encryptor", new EncryptorBeanDefinitionParser(EncryptorFactoryBean.ENCRYPTOR_TYPE_BIG_INTEGER)); registerBeanDefinitionParser("basic-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-text-encryptor", new UtilEncryptorBeanDefinitionParser(UtilEncryptorBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("digester-config", new DigesterConfigBeanDefinitionParser()); registerBeanDefinitionParser("byte-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_BYTE)); registerBeanDefinitionParser("string-digester", new DigesterBeanDefinitionParser(DigesterFactoryBean.DIGESTER_TYPE_STRING)); registerBeanDefinitionParser("basic-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_BASIC)); registerBeanDefinitionParser("strong-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_STRONG)); registerBeanDefinitionParser("configurable-password-encryptor", new UtilDigesterBeanDefinitionParser(UtilDigesterBeanDefinitionParser.UTIL_TYPE_CONFIGURABLE)); registerBeanDefinitionParser("encryptable-properties", new EncryptablePropertiesBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-placeholder", new EncryptablePropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("encryptable-property-override", new EncryptablePropertyOverrideBeanDefinitionParser()); } } EncryptorBeanDefinitionParser.java000066400000000000000000000067241360667575700371450ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class EncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private final int encryptorType; EncryptorBeanDefinitionParser(final int encryptorType) { super(); this.encryptorType = encryptorType; } @Override protected Class getBeanClass(final Element element) { return EncryptorFactoryBean.class; } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { builder.addConstructorArgValue(new Integer(this.encryptorType)); processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } EncryptorConfigBeanDefinitionParser.java000066400000000000000000000274041360667575700402710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.jasypt.encryption.pbe.config.EnvironmentPBEConfig; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; import org.jasypt.encryption.pbe.config.SimplePBEConfig; import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * @since 1.9.3 * * @author Chus Picos * */ final class EncryptorConfigBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; // simple private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_KEY_OBTENTION_ITERATIONS = "key-obtention-iterations"; private static final String PARAM_PASSWORD = "password"; private static final String PARAM_POOL_SIZE = "pool-size"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_CLASS_NAME = "provider-class-name"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_SALT_GENERATOR_BEAN = "salt-generator-bean"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME = "salt-generator-class-name"; private static final String PARAM_IV_GENERATOR_BEAN = "iv-generator-bean"; private static final String PARAM_IV_GENERATOR_CLASS_NAME = "iv-generator-class-name"; private static final Set PARAMS_SIMPLE = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM, PARAM_KEY_OBTENTION_ITERATIONS, PARAM_PASSWORD, PARAM_POOL_SIZE, PARAM_PROVIDER_BEAN, PARAM_PROVIDER_CLASS_NAME, PARAM_PROVIDER_NAME, PARAM_SALT_GENERATOR_BEAN, PARAM_SALT_GENERATOR_CLASS_NAME, PARAM_IV_GENERATOR_BEAN, PARAM_IV_GENERATOR_CLASS_NAME })); // string private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; private static final Set PARAMS_STRING = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE })); // environment private static final String PARAM_ALGORITHM_ENV_NAME = "algorithm-env-name"; private static final String PARAM_ALGORITHM_SYS_PROPERTY_NAME = "algorithm-sys-property-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME = "key-obtention-iterations-env-name"; private static final String PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME = "key-obtention-iterations-sys-property-name"; private static final String PARAM_PASSWORD_ENV_NAME = "password-env-name"; private static final String PARAM_PASSWORD_SYS_PROPERTY_NAME = "password-sys-property-name"; private static final String PARAM_POOL_SIZE_ENV_NAME = "pool-size-env-name"; private static final String PARAM_POOL_SIZE_SYS_PROPERTY_NAME = "pool-size-sys-property-name"; private static final String PARAM_PROVIDER_CLASS_NAME_ENV_NAME = "provider-class-name-env-name"; private static final String PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME = "provider-class-name-sys-property-name"; private static final String PARAM_PROVIDER_NAME_ENV_NAME = "provider-name-env-name"; private static final String PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME = "provider-name-sys-property-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME = "salt-generator-class-name-env-name"; private static final String PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "salt-generator-class-name-sys-property-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME = "iv-generator-class-name-env-name"; private static final String PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME = "iv-generator-class-name-sys-property-name"; private static final Set PARAMS_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_ALGORITHM_ENV_NAME, PARAM_ALGORITHM_SYS_PROPERTY_NAME, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, PARAM_PASSWORD_ENV_NAME, PARAM_PASSWORD_SYS_PROPERTY_NAME, PARAM_POOL_SIZE_ENV_NAME, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_PROVIDER_NAME_ENV_NAME, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME })); // string environment private static final String PARAM_STRING_OUTPUT_TYPE_ENV_NAME = "string-output-type-env-name"; private static final String PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME = "string-output-type-sys-property-name"; private static final Set PARAMS_STRING_ENVIRONMENT = new HashSet(Arrays.asList( new String[] { PARAM_STRING_OUTPUT_TYPE_ENV_NAME, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME })); EncryptorConfigBeanDefinitionParser() { super(); } @Override protected Class getBeanClass(final Element element) { return computeConfigClass(element); } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processIntegerAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS, "keyObtentionIterations"); processStringAttribute(element, builder, PARAM_PASSWORD, "password"); processIntegerAttribute(element, builder, PARAM_POOL_SIZE, "poolSize"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME, "providerClassName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processBeanAttribute(element, builder, PARAM_SALT_GENERATOR_BEAN, "saltGenerator"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME, "saltGeneratorClassName"); processBeanAttribute(element, builder, PARAM_IV_GENERATOR_BEAN, "ivGenerator"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME, "ivGeneratorClassName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); processStringAttribute(element, builder, PARAM_ALGORITHM_ENV_NAME, "algorithmEnvName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_ENV_NAME, "keyObtentionIterationsEnvName"); processStringAttribute(element, builder, PARAM_PASSWORD_ENV_NAME, "passwordEnvName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_ENV_NAME, "poolSizeEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_ENV_NAME, "providerClassNameEnvName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_ENV_NAME, "providerNameEnvName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_ENV_NAME, "saltGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_ENV_NAME, "ivGeneratorClassNameEnvName"); processStringAttribute(element, builder, PARAM_ALGORITHM_SYS_PROPERTY_NAME, "algorithmSysPropertyName"); processStringAttribute(element, builder, PARAM_KEY_OBTENTION_ITERATIONS_SYS_PROPERTY_NAME, "keyObtentionIterationsSysPropertyName"); processStringAttribute(element, builder, PARAM_PASSWORD_SYS_PROPERTY_NAME, "passwordSysPropertyName"); processStringAttribute(element, builder, PARAM_POOL_SIZE_SYS_PROPERTY_NAME, "poolSizeSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_CLASS_NAME_SYS_PROPERTY_NAME, "providerClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME_SYS_PROPERTY_NAME, "providerNameSysPropertyName"); processStringAttribute(element, builder, PARAM_SALT_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "saltGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_IV_GENERATOR_CLASS_NAME_SYS_PROPERTY_NAME, "ivGeneratorClassNameSysPropertyName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_ENV_NAME, "stringOutputTypeEnvName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE_SYS_PROPERTY_NAME, "stringOutputTypeSysPropertyName"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } private static Class computeConfigClass(final Element element) { boolean isSimpleConfig = false; boolean isStringConfig = false; boolean isEnvironmentConfig = false; boolean isStringEnvironmentConfig = false; final NamedNodeMap attributesMap = element.getAttributes(); final int attributesLen = attributesMap.getLength(); for (int i = 0; i < attributesLen; i++) { final Node attribute = attributesMap.item(i); final String attributeName = attribute.getNodeName(); if (!isSimpleConfig && PARAMS_SIMPLE.contains(attributeName)) { isSimpleConfig = true; } if (!isStringConfig && PARAMS_STRING.contains(attributeName)) { isStringConfig = true; } if (!isEnvironmentConfig && PARAMS_ENVIRONMENT.contains(attributeName)) { isEnvironmentConfig = true; } if (!isStringEnvironmentConfig && PARAMS_STRING_ENVIRONMENT.contains(attributeName)) { isStringEnvironmentConfig = true; } } if (isStringEnvironmentConfig || (isEnvironmentConfig && isStringConfig)) { return EnvironmentStringPBEConfig.class; } if (isEnvironmentConfig) { return EnvironmentPBEConfig.class; } if (isStringConfig) { return SimpleStringPBEConfig.class; } return SimplePBEConfig.class; } } EncryptorFactoryBean.java000066400000000000000000000256331360667575700353070ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import java.beans.Statement; import java.security.Provider; import org.jasypt.encryption.pbe.PBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.PooledPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.PooledPBEByteEncryptor; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; /** *

* Factory bean for creating encryptor objects from the encryption namespace * elements. Do not use directly. *

* * * @since 1.9.3 * * @author Chus Picos * */ public final class EncryptorFactoryBean implements FactoryBean, InitializingBean { static final int ENCRYPTOR_TYPE_BYTE = 0; static final int ENCRYPTOR_TYPE_STRING = 1; static final int ENCRYPTOR_TYPE_BIG_DECIMAL = 2; static final int ENCRYPTOR_TYPE_BIG_INTEGER = 3; private final int encryptorType; private boolean singleton = true; private Object singletonInstance = null; private boolean algorithmSet = false; private String algorithm = null; private boolean configSet = false; private PBEConfig config = null; private boolean keyObtentionIterationsSet = false; private Integer keyObtentionIterations = null; private boolean passwordSet = false; private String password = null; private boolean poolSizeSet = false; private Integer poolSize = null; private boolean providerSet = false; private Provider provider = null; private boolean providerNameSet = false; private String providerName = null; private boolean saltGeneratorSet = false; private SaltGenerator saltGenerator = null; private boolean ivGeneratorSet = false; private IvGenerator ivGenerator = null; private boolean stringOutputTypeSet = false; private String stringOutputType = null; public EncryptorFactoryBean(final int encryptorType) { super(); this.encryptorType = encryptorType; } public final void setSingleton(boolean singleton) { this.singleton = singleton; } public final boolean isSingleton() { return this.singleton; } public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; this.algorithmSet = true; } public void setConfig(final PBEConfig config) { this.config = config; this.configSet = true; } public void setKeyObtentionIterations(final Integer keyObtentionIterations) { this.keyObtentionIterations = keyObtentionIterations; this.keyObtentionIterationsSet = true; } public void setPassword(final String password) { this.password = password; this.passwordSet = true; } public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; this.poolSizeSet = true; } public void setProvider(final Provider provider) { this.provider = provider; this.providerSet = true; } public void setProviderName(final String providerName) { this.providerName = providerName; this.providerNameSet = true; } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } public void setIvGenerator(final IvGenerator ivGenerator) { this.ivGenerator = ivGenerator; this.ivGeneratorSet = true; } public void setStringOutputType(final String stringOutputType) { this.stringOutputType = stringOutputType; this.stringOutputTypeSet = true; } public final void afterPropertiesSet() throws Exception { if (this.singleton) { this.singletonInstance = computeObject(); } } public Object getObject() throws Exception { if (this.singleton) { return this.singletonInstance; } return computeObject(); } private Object computeObject() throws Exception { Object encryptor = null; if (isPooled()) { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new PooledPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new PooledPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new PooledPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new PooledPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } if (this.poolSizeSet && this.poolSize != null) { final Statement st = new Statement( encryptor, "setPoolSize", new Object[] { this.poolSize }); st.execute(); } } else { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { encryptor = new StandardPBEByteEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { encryptor = new StandardPBEStringEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { encryptor = new StandardPBEBigDecimalEncryptor(); } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { encryptor = new StandardPBEBigIntegerEncryptor(); } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } if (this.algorithmSet) { final Statement st = new Statement( encryptor, "setAlgorithm", new Object[] { this.algorithm }); st.execute(); } if (this.configSet) { final Statement st = new Statement( encryptor, "setConfig", new Object[] { this.config }); st.execute(); } if (this.keyObtentionIterationsSet && this.keyObtentionIterations != null) { final Statement st = new Statement( encryptor, "setKeyObtentionIterations", new Object[] { this.keyObtentionIterations }); st.execute(); } if (this.passwordSet) { final Statement st = new Statement( encryptor, "setPassword", new Object[] { this.password }); st.execute(); } if (this.providerSet) { final Statement st = new Statement( encryptor, "setProvider", new Object[] { this.provider }); st.execute(); } if (this.providerNameSet) { final Statement st = new Statement( encryptor, "setProviderName", new Object[] { this.providerName }); st.execute(); } if (this.saltGeneratorSet) { final Statement st = new Statement( encryptor, "setSaltGenerator", new Object[] { this.saltGenerator }); st.execute(); } if (this.ivGeneratorSet) { final Statement st = new Statement( encryptor, "setIvGenerator", new Object[] { this.ivGenerator }); st.execute(); } if (this.stringOutputTypeSet && encryptor instanceof PBEStringEncryptor) { final Statement st = new Statement( encryptor, "setStringOutputType", new Object[] { this.stringOutputType }); st.execute(); } return encryptor; } public Class getObjectType() { if (this.encryptorType == ENCRYPTOR_TYPE_BYTE) { return PBEByteEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_STRING) { return PBEStringEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_DECIMAL) { return PBEBigDecimalEncryptor.class; } else if (this.encryptorType == ENCRYPTOR_TYPE_BIG_INTEGER) { return PBEBigIntegerEncryptor.class; } else { throw new IllegalArgumentException("Unknown encryptor type: " + this.encryptorType); } } private boolean isPooled() { if (this.poolSizeSet && this.poolSize != null) { return true; } if (this.configSet && this.config != null) { return this.config.getPoolSize() != null; } return false; } } UtilDigesterBeanDefinitionParser.java000066400000000000000000000063641360667575700375640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.ConfigurablePasswordEncryptor; import org.jasypt.util.password.StrongPasswordEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class UtilDigesterBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_ALGORITHM = "algorithm"; private static final String PARAM_CONFIG_BEAN = "config-bean"; private static final String PARAM_PROVIDER_BEAN = "provider-bean"; private static final String PARAM_PROVIDER_NAME = "provider-name"; private static final String PARAM_STRING_OUTPUT_TYPE = "string-output-type"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; static final int UTIL_TYPE_CONFIGURABLE = 2; private final int utilType; UtilDigesterBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongPasswordEncryptor.class; } else if (this.utilType == UTIL_TYPE_CONFIGURABLE) { return ConfigurablePasswordEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_ALGORITHM, "algorithm"); processBeanAttribute(element, builder, PARAM_CONFIG_BEAN, "config"); processBeanAttribute(element, builder, PARAM_PROVIDER_BEAN, "provider"); processStringAttribute(element, builder, PARAM_PROVIDER_NAME, "providerName"); processStringAttribute(element, builder, PARAM_STRING_OUTPUT_TYPE, "stringOutputType"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } UtilEncryptorBeanDefinitionParser.java000066400000000000000000000045711360667575700400010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring4.xml.encryption; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.StrongTextEncryptor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * * @since 1.9.3 * * @author Chus Picos * */ final class UtilEncryptorBeanDefinitionParser extends AbstractEncryptionBeanDefinitionParser { private static final String SCOPE_ATTRIBUTE = "scope"; private static final String PARAM_PASSWORD = "password"; static final int UTIL_TYPE_BASIC = 0; static final int UTIL_TYPE_STRONG = 1; private final int utilType; UtilEncryptorBeanDefinitionParser(final int utilType) { super(); this.utilType = utilType; } @Override protected Class getBeanClass(final Element element) { if (this.utilType == UTIL_TYPE_BASIC) { return BasicTextEncryptor.class; } else if (this.utilType == UTIL_TYPE_STRONG) { return StrongTextEncryptor.class; } else { throw new IllegalArgumentException("Unknown util type: " + this.utilType); } } @Override protected void doParse(final Element element, final BeanDefinitionBuilder builder) { processStringAttribute(element, builder, PARAM_PASSWORD, "password"); String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } } jasypt-spring4-encryption-1.xsd000066400000000000000000001260501360667575700363000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/java/org/jasypt/spring4/xml/encryption jasypt-jasypt-1.9.3/jasypt-spring4/src/main/metainf/000077500000000000000000000000001360667575700224305ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/main/metainf/spring.handlers000066400000000000000000000001461360667575700254550ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption=org.jasypt.spring4.xml.encryption.EncryptionNamespaceHandler jasypt-jasypt-1.9.3/jasypt-spring4/src/main/metainf/spring.schemas000066400000000000000000000002131360667575700252730ustar00rootroot00000000000000http\://www.jasypt.org/schema/encryption/jasypt-spring4-encryption-1.xsd=org/jasypt/spring4/xml/encryption/jasypt-spring4-encryption-1.xsd jasypt-jasypt-1.9.3/jasypt-spring4/src/test/000077500000000000000000000000001360667575700210405ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/000077500000000000000000000000001360667575700217615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/org/000077500000000000000000000000001360667575700225505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/org/jasypt/000077500000000000000000000000001360667575700240625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/org/jasypt/spring4/000077500000000000000000000000001360667575700254505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/org/jasypt/spring4/properties/000077500000000000000000000000001360667575700276445ustar00rootroot00000000000000EncryptablePropertyPlaceholderConfigurerTest.java000066400000000000000000000145131360667575700415000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-spring4/src/test/java/org/jasypt/spring4/propertiespackage org.jasypt.spring4.properties; import java.util.HashMap; import java.util.Map; import org.jasypt.encryption.StringEncryptor; import org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer; import org.jasypt.util.text.TextEncryptor; import junit.framework.TestCase; /* * ==Test resolveSystemProperty for encrypted env var== * * I don't have a great way to test the decryption of encrypted env var without requiring the test harness (surefire, IDE etc) * to have specified an encrypted environment variable. Here are a few options * - reflection hack to change the underlying system env map - * http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java. THis is what spring does to * test the propertyplaceholderconfigurer: * https://src.springframework.org/svn/spring-framework/trunk/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurerTests.java * - extract the call to super.resolveSystemProperty(key) in resolveSystemProperty to a protected method and the test * will use a testspecifc subclass (http://xunitpatterns.com/Test-Specific%20Subclass.html) that overrides that method. * * However, i really don't think it is that big of a deal. The functionality responsible for getting system/env values * is defined in the super. All this class does is check to see if they have the encryption delimiters. I am pretty sure * I already went overboard on the test - ~100 lines of test for 3 lines of production code. * * @author Chus Picos */ public class EncryptablePropertyPlaceholderConfigurerTest extends TestCase { //duplicated prefix suffix values in PropertyValueEncryptionUtils because PVEU constants are private private static final String ENCRYPTED_VALUE_PREFIX = "ENC("; private static final String ENCRYPTED_VALUE_SUFFIX = ")"; private String expectedDecryptedValue; private String encryptedValue; private String encryptedValueWithDelimiters; private String encryptedSysPropKey; private String unencryptedSysPropKey; private String unencryptedValue; public void setUp() { this.encryptedSysPropKey = "thisIsAnEncryptedSysPropertyKey"; this.encryptedValue = "encryptedString"; this.encryptedValueWithDelimiters = ENCRYPTED_VALUE_PREFIX + this.encryptedValue + ENCRYPTED_VALUE_SUFFIX; this.expectedDecryptedValue = "clearText"; System.setProperty(this.encryptedSysPropKey, this.encryptedValueWithDelimiters); this.unencryptedSysPropKey = "thisIsAnUNEncryptedSysPropertyKey"; this.unencryptedValue = "thisIsARegularString"; System.setProperty(this.unencryptedSysPropKey, this.unencryptedValue); } public void testConvertPropertyValueNotEncrypted() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(this.unencryptedValue, eppc.convertPropertyValue(this.unencryptedValue)); } public void testConvertPropertyValueDecryptWithStringEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithStringEncryptor(); assertEquals(this.expectedDecryptedValue, eppc.convertPropertyValue(this.encryptedValueWithDelimiters)); } public void testConvertPropertyValueDecryptWithTextEncryptor() { EncryptablePropertyPlaceholderConfigurer eppc = createPPCWithTextEncryptor(); assertEquals(this.expectedDecryptedValue, eppc.convertPropertyValue(this.encryptedValueWithDelimiters)); } public void testResolveSystemPropertyNullSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertNull(ppc.resolveSystemProperty("foofoofoo")); } public void testResolveSystemPropertyEncryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); assertEquals(this.expectedDecryptedValue, ppc.resolveSystemProperty(this.encryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedSystemPropertyValue() throws Exception { EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithStringEncryptor(); assertEquals(this.unencryptedValue, ppc.resolveSystemProperty(this.unencryptedSysPropKey)); } public void testResolveSystemPropertyUnencryptedEnvVar() throws Exception { //the expectation is that the system has the HOME env var String unencryptedEnvVarKey = "HOME";//this is expected to exist on windows and unix systems String unencryptedEnvVarValue = System.getenv(unencryptedEnvVarKey); //lets make sure the env variable is set & is not null assertNotNull("no home env variable found", unencryptedEnvVarValue); EncryptablePropertyPlaceholderConfigurer ppc = createPPCWithTextEncryptor(); //allow ppc can check env vars ppc.setSearchSystemEnvironment(true); assertEquals(unencryptedEnvVarValue, ppc.resolveSystemProperty(unencryptedEnvVarKey)); } private EncryptablePropertyPlaceholderConfigurer createPPCWithTextEncryptor() { StubTextEncryptor textEncryptor = new StubTextEncryptor(); textEncryptor.addDecryption(this.encryptedValue, this.expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(textEncryptor); } private EncryptablePropertyPlaceholderConfigurer createPPCWithStringEncryptor() { StubStringEncryptor stringEncryptor = new StubStringEncryptor(); stringEncryptor.addDecryption(this.encryptedValue, expectedDecryptedValue); return new EncryptablePropertyPlaceholderConfigurer(stringEncryptor); } abstract class StubEncryptor { private Map decryptMap = new HashMap(); public String decrypt(String encryptedMessage) { return (String)this.decryptMap.get(encryptedMessage); } public String encrypt(String message) { throw new UnsupportedOperationException(); } public void addDecryption(String encrypted, String expectedDecryption) { this.decryptMap.put(encrypted, expectedDecryption); } } class StubStringEncryptor extends StubEncryptor implements StringEncryptor{} class StubTextEncryptor extends StubEncryptor implements TextEncryptor{} } jasypt-jasypt-1.9.3/jasypt-springsecurity2/000077500000000000000000000000001360667575700210605ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/.gitignore000066400000000000000000000000721360667575700230470ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-springsecurity2/BUILD.txt000066400000000000000000000016001360667575700224550ustar00rootroot00000000000000 Building JASYPT-SPRINGSECURITY2 ------------------------------- To build JASYPT-SPRINGSECURITY2 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRINGSECURITY2 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-springsecurity2-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-springsecurity2/{version}/jasypt-springsecurity2-{version}.jar Generating Javadoc for JASYPT-SPRINGSECURITY2 --------------------------------------------- If you wish to generate the javadoc for JASYPT-SPRINGSECURITY2, execute this from the JASYPT-SPRINGSECURITY2 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-springsecurity2/ChangeLog.txt000066400000000000000000000005631360667575700234540ustar00rootroot000000000000001.9.3 ===== - Deprecated in 1.9.3. This module will be removed in 2.0.0. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-springsecurity2 package from previous monolithic jasypt module. - Renamed org.jasypt.spring.security2 package as org.jasypt.springsecurity2.providers.encoding, and deprecated the classes in the old package. jasypt-jasypt-1.9.3/jasypt-springsecurity2/LICENSE.txt000066400000000000000000000261361360667575700227130ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-springsecurity2/NOTICE.txt000066400000000000000000000072671360667575700226160ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-springsecurity2/README.txt000066400000000000000000000006111360667575700225540ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-springsecurity2/RELEASING.txt000066400000000000000000000023061360667575700231330ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-springsecurity2/USAGE.txt000066400000000000000000000012231360667575700224630ustar00rootroot00000000000000 Using JASYPT-SPRINGSECURITY2 from Maven 2 ----------------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-springsecurity2 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-springsecurity2/pom.xml000066400000000000000000000165641360667575700224110ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-springsecurity2 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework.security spring-security-core 2.0.0 provided true org.springframework spring-dao 2.0.8 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/000077500000000000000000000000001360667575700216475ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/000077500000000000000000000000001360667575700225735ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/000077500000000000000000000000001360667575700235145ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/000077500000000000000000000000001360667575700243035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/000077500000000000000000000000001360667575700256155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/spring/000077500000000000000000000000001360667575700271175ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/spring/security2/000077500000000000000000000000001360667575700310505ustar00rootroot00000000000000PBEPasswordEncoder.java000066400000000000000000000237371360667575700353010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/spring/security2/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security2; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security 2.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in Spring Security using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.5 * * @author Daniel Fernández * * @deprecated Renamed as org.jasypt.springsecurity2.providers.encoding.PBEPasswordEncoder. * Class will be removed from this package in 1.11. * */ public final class PBEPasswordEncoder implements org.springframework.security.providers.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000222771360667575700347500ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/spring/security2/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security2; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security 2.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.5 * * @author Daniel Fernández * * @deprecated Renamed as org.jasypt.springsecurity2.providers.encoding.PasswordEncoder. * Class will be removed from this package in 1.11. * */ public final class PasswordEncoder implements org.springframework.security.providers.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/springsecurity2/000077500000000000000000000000001360667575700307715ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/springsecurity2/providers/000077500000000000000000000000001360667575700330065ustar00rootroot00000000000000encoding/000077500000000000000000000000001360667575700345155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/springsecurity2/providersPBEPasswordEncoder.java000066400000000000000000000237371360667575700410250ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/springsecurity2/providers/encoding/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity2.providers.encoding; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security 2.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in Spring Security using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security2.PasswordEncoder since 1.5) * * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class PBEPasswordEncoder implements org.springframework.security.providers.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000223021360667575700404610ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity2/src/main/java/org/jasypt/springsecurity2/providers/encoding/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity2.providers.encoding; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security 2.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security2.PasswordEncoder since 1.5) * * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class PasswordEncoder implements org.springframework.security.providers.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-springsecurity3/000077500000000000000000000000001360667575700210615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/.gitignore000066400000000000000000000000721360667575700230500ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-springsecurity3/BUILD.txt000066400000000000000000000016001360667575700224560ustar00rootroot00000000000000 Building JASYPT-SPRINGSECURITY3 ------------------------------- To build JASYPT-SPRINGSECURITY3 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRINGSECURITY3 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-springsecurity3-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-springsecurity3/{version}/jasypt-springsecurity3-{version}.jar Generating Javadoc for JASYPT-SPRINGSECURITY3 --------------------------------------------- If you wish to generate the javadoc for JASYPT-SPRINGSECURITY3, execute this from the JASYPT-SPRINGSECURITY3 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-springsecurity3/ChangeLog.txt000066400000000000000000000006031360667575700234500ustar00rootroot000000000000001.9.3 ===== (no changes) 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-springsecurity3 package from previous monolithic jasypt module. - Renamed org.jasypt.spring.security3 package as org.jasypt.springsecurity3.authentication.encoding and org.jasypt.springsecurity3.authentication.rememberme, and deprecated the classes in the old package. jasypt-jasypt-1.9.3/jasypt-springsecurity3/LICENSE.txt000066400000000000000000000261361360667575700227140ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-springsecurity3/NOTICE.txt000066400000000000000000000072671360667575700226170ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-springsecurity3/README.txt000066400000000000000000000006111360667575700225550ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-springsecurity3/RELEASING.txt000066400000000000000000000023061360667575700231340ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-springsecurity3/USAGE.txt000066400000000000000000000012231360667575700224640ustar00rootroot00000000000000 Using JASYPT-SPRINGSECURITY3 from Maven 2 ----------------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-springsecurity3 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-springsecurity3/pom.xml000066400000000000000000000171471360667575700224100ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-springsecurity3 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework.security spring-security-core 3.0.0.RELEASE provided true org.springframework.security spring-security-web 3.0.0.RELEASE provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/000077500000000000000000000000001360667575700216505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/000077500000000000000000000000001360667575700225745ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/000077500000000000000000000000001360667575700235155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/000077500000000000000000000000001360667575700243045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/000077500000000000000000000000001360667575700256165ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/spring/000077500000000000000000000000001360667575700271205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/spring/security3/000077500000000000000000000000001360667575700310525ustar00rootroot00000000000000PBEPasswordEncoder.java000066400000000000000000000237511360667575700352770ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/spring/security3/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security3; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security 3.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in Spring Security using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.6 * * @deprecated Renamed as org.jasypt.springsecurity3.authentication.encoding.PBEPasswordEncoder. * Class will be removed from this package in 1.11. * * @author Daniel Fernández * */ public final class PBEPasswordEncoder implements org.springframework.security.authentication.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000223161360667575700347440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/spring/security3/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security3; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security 3.x * org.springframework.security.authentication.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.6 * * @author Daniel Fernández * * @deprecated Renamed as org.jasypt.springsecurity3.authentication.encoding.PasswordEncoder. * Class will be removed from this package in 1.11. * */ public final class PasswordEncoder implements org.springframework.security.authentication.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } TokenBasedRememberMeServices.java000066400000000000000000000144151360667575700373270ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/spring/security3/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.spring.security3; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.StringDigester; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; import org.springframework.security.web.authentication.rememberme.InvalidCookieException; /** *

* Implementation of org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices * which provides a "remember-me" cookie arranged in the same way as * org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices, but using a * Jasypt {@link StringDigester} passed as a parameter for performing the digest of the signature in the cookie * (username + ":" + expiry time + ":" + password + ":" + key). *

*

* This class is thread-safe *

* * @since 1.7 * * @author Daniel Fernández * * @deprecated Renamed as org.jasypt.springsecurity3.authentication.rememberme.TokenBasedRememberMeServices. * Class will be removed from this package in 1.11. * */ public final class TokenBasedRememberMeServices extends AbstractRememberMeServices { private StringDigester digester = null; public void setDigester(final StringDigester digester) { this.digester = digester; } private String getSignatureData(final long tokenExpiryTime, final String username, final String password) { return username + ":" + tokenExpiryTime + ":" + password + ":" + getKey(); } protected UserDetails processAutoLoginCookie(final String[] cookieTokens, final HttpServletRequest request, final HttpServletResponse response) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } if (cookieTokens.length != 3) { throw new InvalidCookieException("Wrong number of tokens in cookie"); } final String usernameToken = cookieTokens[0]; final String expiryToken = cookieTokens[1]; final String digestedSignature = cookieTokens[2]; long expiryTimestamp = -1; try { expiryTimestamp = new Long(expiryToken).longValue(); } catch (NumberFormatException nfe) { throw new InvalidCookieException("Invalid cookie expiry token"); } if (expiryTimestamp < System.currentTimeMillis()) { // Cookie has expired throw new InvalidCookieException("Cookie has expired (expired on '" + new Date(expiryTimestamp) + "'; current time is '" + new Date() + "')"); } // Retrieve user details final UserDetails userDetails = getUserDetailsService().loadUserByUsername(usernameToken); final String username = userDetails.getUsername(); final String password = userDetails.getPassword(); // Check signature data if (!this.digester.matches(getSignatureData(expiryTimestamp, username, password), digestedSignature)) { throw new InvalidCookieException("Cookie signature is not valid"); } return userDetails; } public void onLoginSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication successfulAuthentication) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } String username = null; String password = null; if (successfulAuthentication.getPrincipal() instanceof UserDetails) { final UserDetails userDetails = (UserDetails) successfulAuthentication.getPrincipal(); username = userDetails.getUsername(); password = userDetails.getPassword(); } else { username = successfulAuthentication.getPrincipal().toString(); password = (successfulAuthentication.getCredentials() == null? null : successfulAuthentication.getCredentials().toString()); } if (CommonUtils.isEmpty(username) || CommonUtils.isEmpty(password)) { // both user name and password have to be non-empty. No cookie to be added return; } final int tokenValiditySeconds = getTokenValiditySeconds(); final long expiryTime = System.currentTimeMillis() + 1000L* (tokenValiditySeconds < 0 ? TWO_WEEKS_S : tokenValiditySeconds); final String signature = this.digester.digest(getSignatureData(expiryTime, username, password)); setCookie(new String[] {username, Long.toString(expiryTime), signature}, tokenValiditySeconds, request, response); if (this.logger.isDebugEnabled()) { this.logger.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'"); } } } jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/000077500000000000000000000000001360667575700307735ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authentication/000077500000000000000000000000001360667575700340125ustar00rootroot00000000000000encoding/000077500000000000000000000000001360667575700355215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authenticationPBEPasswordEncoder.java000066400000000000000000000236431360667575700420250ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authentication/encoding/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity3.authentication.encoding; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security 3.x * org.springframework.security.providers.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in Spring Security using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * TextEncryptor or PBEStringEncryptor objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security3.PBEPasswordEncoder since 1.6) * * @author Daniel Fernández * */ public final class PBEPasswordEncoder implements org.springframework.security.authentication.encoding.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPass); } return this.pbeStringEncryptor.encrypt(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's TextEncryptor and PBEStringEncryptor * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encPass); } else { decPassword = this.pbeStringEncryptor.decrypt(encPass); } if ((decPassword == null) || (rawPass == null)) { return (decPassword == rawPass); } return decPassword.equals(rawPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000222101360667575700414630ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authentication/encoding/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity3.authentication.encoding; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security 3.x * org.springframework.security.authentication.encoding.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Important: This implementation ignores any salt provided through * the interface methods, as the internal Jasypt * PasswordEncryptor or StringDigester objects normally use a * random one. This means that salt can be safely passed as * null. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.spring.security2.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security3.PasswordEncoder since 1.6) * * @author Daniel Fernández * */ public final class PasswordEncoder implements org.springframework.security.authentication.encoding.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. This implementation completely ignores salt, * as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param rawPass The password to be encoded. * @param salt The salt, which will be ignored. It can be null. */ public String encodePassword(final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPass); } return this.stringDigester.digest(rawPass); } /** * Checks a password's validity. This implementation completely ignores * salt, as jasypt's PasswordEncryptor and StringDigester * normally use a random one. Thus, it can be safely passed as null. * * @param encPass The encrypted password (digest) against which to check. * @param rawPass The password to be checked. * @param salt The salt, which will be ignored. It can be null. */ public boolean isPasswordValid(final String encPass, final String rawPass, final Object salt) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPass, encPass); } return this.stringDigester.matches(rawPass, encPass); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } rememberme/000077500000000000000000000000001360667575700360535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authenticationTokenBasedRememberMeServices.java000066400000000000000000000143071360667575700444070ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity3/src/main/java/org/jasypt/springsecurity3/authentication/rememberme/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity3.authentication.rememberme; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.StringDigester; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; import org.springframework.security.web.authentication.rememberme.InvalidCookieException; /** *

* Implementation of org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices * which provides a "remember-me" cookie arranged in the same way as * org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices, but using a * Jasypt {@link StringDigester} passed as a parameter for performing the digest of the signature in the cookie * (username + ":" + expiry time + ":" + password + ":" + key). *

*

* This class is thread-safe *

* * @since 1.9.0 (existed as org.jasypt.spring.security3.TokenBasedRememberMeServices since 1.7) * * @author Daniel Fernández * */ public final class TokenBasedRememberMeServices extends AbstractRememberMeServices { private StringDigester digester = null; public void setDigester(final StringDigester digester) { this.digester = digester; } private String getSignatureData(final long tokenExpiryTime, final String username, final String password) { return username + ":" + tokenExpiryTime + ":" + password + ":" + getKey(); } protected UserDetails processAutoLoginCookie(final String[] cookieTokens, final HttpServletRequest request, final HttpServletResponse response) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } if (cookieTokens.length != 3) { throw new InvalidCookieException("Wrong number of tokens in cookie"); } final String usernameToken = cookieTokens[0]; final String expiryToken = cookieTokens[1]; final String digestedSignature = cookieTokens[2]; long expiryTimestamp = -1; try { expiryTimestamp = new Long(expiryToken).longValue(); } catch (NumberFormatException nfe) { throw new InvalidCookieException("Invalid cookie expiry token"); } if (expiryTimestamp < System.currentTimeMillis()) { // Cookie has expired throw new InvalidCookieException("Cookie has expired (expired on '" + new Date(expiryTimestamp) + "'; current time is '" + new Date() + "')"); } // Retrieve user details final UserDetails userDetails = getUserDetailsService().loadUserByUsername(usernameToken); final String username = userDetails.getUsername(); final String password = userDetails.getPassword(); // Check signature data if (!this.digester.matches(getSignatureData(expiryTimestamp, username, password), digestedSignature)) { throw new InvalidCookieException("Cookie signature is not valid"); } return userDetails; } public void onLoginSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication successfulAuthentication) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } String username = null; String password = null; if (successfulAuthentication.getPrincipal() instanceof UserDetails) { final UserDetails userDetails = (UserDetails) successfulAuthentication.getPrincipal(); username = userDetails.getUsername(); password = userDetails.getPassword(); } else { username = successfulAuthentication.getPrincipal().toString(); password = (successfulAuthentication.getCredentials() == null? null : successfulAuthentication.getCredentials().toString()); } if (CommonUtils.isEmpty(username) || CommonUtils.isEmpty(password)) { // both user name and password have to be non-empty. No cookie to be added return; } final int tokenValiditySeconds = getTokenValiditySeconds(); final long expiryTime = System.currentTimeMillis() + 1000L* (tokenValiditySeconds < 0 ? TWO_WEEKS_S : tokenValiditySeconds); final String signature = this.digester.digest(getSignatureData(expiryTime, username, password)); setCookie(new String[] {username, Long.toString(expiryTime), signature}, tokenValiditySeconds, request, response); if (this.logger.isDebugEnabled()) { this.logger.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'"); } } } jasypt-jasypt-1.9.3/jasypt-springsecurity4/000077500000000000000000000000001360667575700210625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/.gitignore000066400000000000000000000000721360667575700230510ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-springsecurity4/BUILD.txt000066400000000000000000000016001360667575700224570ustar00rootroot00000000000000 Building JASYPT-SPRINGSECURITY4 ------------------------------- To build JASYPT-SPRINGSECURITY4 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-SPRINGSECURITY4 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-springsecurity4-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-springsecurity4/{version}/jasypt-springsecurity4-{version}.jar Generating Javadoc for JASYPT-SPRINGSECURITY4 --------------------------------------------- If you wish to generate the javadoc for JASYPT-SPRINGSECURITY4, execute this from the JASYPT-SPRINGSECURITY4 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-springsecurity4/ChangeLog.txt000066400000000000000000000001361360667575700234520ustar00rootroot000000000000001.9.3 ===== - Created new jasypt-springsecurity4 module for Spring Security 4 integration.jasypt-jasypt-1.9.3/jasypt-springsecurity4/LICENSE.txt000066400000000000000000000261361360667575700227150ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-springsecurity4/NOTICE.txt000066400000000000000000000072671360667575700226200ustar00rootroot00000000000000 Copyright (c) 2007-2017, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-springsecurity4/README.txt000066400000000000000000000006111360667575700225560ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-springsecurity4/RELEASING.txt000066400000000000000000000023061360667575700231350ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-springsecurity4/USAGE.txt000066400000000000000000000012231360667575700224650ustar00rootroot00000000000000 Using JASYPT-SPRINGSECURITY4 from Maven 2 ----------------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-springsecurity4 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-springsecurity4/pom.xml000066400000000000000000000177511360667575700224120ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-springsecurity4 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD chuspicosvilar Chus Picos chuspicosvilar AT users.sourceforge.net Developer hokitorres Hoki Torres hokitorres AT users.sourceforge.net Developer sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.springframework.security spring-security-core 4.0.0.RELEASE provided true org.springframework.security spring-security-web 4.0.0.RELEASE provided true javax.servlet servlet-api 2.5 provided true junit junit 3.8.1 test commons-lang commons-lang 2.1 test commons-logging commons-logging 1.2 compile jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/000077500000000000000000000000001360667575700216515ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/000077500000000000000000000000001360667575700225755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/000077500000000000000000000000001360667575700235165ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/000077500000000000000000000000001360667575700243055ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/000077500000000000000000000000001360667575700256175ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/000077500000000000000000000000001360667575700307755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/authentication/000077500000000000000000000000001360667575700340145ustar00rootroot00000000000000rememberme/000077500000000000000000000000001360667575700360555ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/authenticationTokenBasedRememberMeServices.java000066400000000000000000000144731360667575700444150ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/authentication/rememberme/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity4.authentication.rememberme; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.StringDigester; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; import org.springframework.security.web.authentication.rememberme.InvalidCookieException; /** *

* Implementation of org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices * which provides a "remember-me" cookie arranged in the same way as * org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices, but using a * Jasypt {@link StringDigester} passed as a parameter for performing the digest of the signature in the cookie * (username + ":" + expiry time + ":" + password + ":" + key). *

*

* This class is thread-safe *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class TokenBasedRememberMeServices extends AbstractRememberMeServices { private StringDigester digester = null; protected TokenBasedRememberMeServices(String key, UserDetailsService userDetailsService) { super(key, userDetailsService); } public void setDigester(final StringDigester digester) { this.digester = digester; } private String getSignatureData(final long tokenExpiryTime, final String username, final String password) { return username + ":" + tokenExpiryTime + ":" + password + ":" + getKey(); } protected UserDetails processAutoLoginCookie(final String[] cookieTokens, final HttpServletRequest request, final HttpServletResponse response) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } if (cookieTokens.length != 3) { throw new InvalidCookieException("Wrong number of tokens in cookie"); } final String usernameToken = cookieTokens[0]; final String expiryToken = cookieTokens[1]; final String digestedSignature = cookieTokens[2]; long expiryTimestamp = -1; try { expiryTimestamp = new Long(expiryToken).longValue(); } catch (NumberFormatException nfe) { throw new InvalidCookieException("Invalid cookie expiry token"); } if (expiryTimestamp < System.currentTimeMillis()) { // Cookie has expired throw new InvalidCookieException("Cookie has expired (expired on '" + new Date(expiryTimestamp) + "'; current time is '" + new Date() + "')"); } // Retrieve user details final UserDetails userDetails = getUserDetailsService().loadUserByUsername(usernameToken); final String username = userDetails.getUsername(); final String password = userDetails.getPassword(); // Check signature data if (!this.digester.matches(getSignatureData(expiryTimestamp, username, password), digestedSignature)) { throw new InvalidCookieException("Cookie signature is not valid"); } return userDetails; } public void onLoginSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication successfulAuthentication) { if (this.digester == null) { throw new IllegalStateException("Service incorrectly initialized: a " + "digester has not been set. A value must be specified for the \"digester\"" + " property in service of class " + this.getClass().getName()); } String username = null; String password = null; if (successfulAuthentication.getPrincipal() instanceof UserDetails) { final UserDetails userDetails = (UserDetails) successfulAuthentication.getPrincipal(); username = userDetails.getUsername(); password = userDetails.getPassword(); } else { username = successfulAuthentication.getPrincipal().toString(); password = (successfulAuthentication.getCredentials() == null? null : successfulAuthentication.getCredentials().toString()); } if (CommonUtils.isEmpty(username) || CommonUtils.isEmpty(password)) { // both user name and password have to be non-empty. No cookie to be added return; } final int tokenValiditySeconds = getTokenValiditySeconds(); final long expiryTime = System.currentTimeMillis() + 1000L* (tokenValiditySeconds < 0 ? TWO_WEEKS_S : tokenValiditySeconds); final String signature = this.digester.digest(getSignatureData(expiryTime, username, password)); setCookie(new String[] {username, Long.toString(expiryTime), signature}, tokenValiditySeconds, request, response); if (this.logger.isDebugEnabled()) { this.logger.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'"); } } } jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/crypto/000077500000000000000000000000001360667575700323155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/crypto/password/000077500000000000000000000000001360667575700341575ustar00rootroot00000000000000PBEPasswordEncoder.java000066400000000000000000000220741360667575700404010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/crypto/password/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity4.crypto.password; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.text.BasicTextEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* This class implements the Spring Security 4.x * org.springframework.security.crypto.password.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Important: This class allows bi-directional password-based encryption * of user passwords * in Spring Security using Jasypt. But please note that passwords should not be * encrypted in a bi-directional way, but instead as uni-directional * digests (hashes). Encrypting passwords in a way they can be decrypted * can be a severe security issue, and should only be considered in legacy * or complex inter-application integration scenarios. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.text.TextEncryptor or an object of type * org.jasypt.encryption.pbe.PBEStringEncryptor (only one of them), * which should be set by respectively calling * {@link #setTextEncryptor(TextEncryptor)} or * {@link #setPbeStringEncryptor(PBEStringEncryptor)} * after creation. If neither a TextEncryptor nor * a PBEStringEncryptor are set, a new * org.jasypt.util.text.BasicTextEncryptor object is * created and internally used. *

*

* Usage with a TextEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the TextEncryptor in several places,     --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptTextEncryptor" class="org.jasypt.util.text.StrongTextEncryptor" >
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the TextEncryptor instance so that it can be used from       -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.springsecurity4.crypto.password.PBEPasswordEncoder">
 *    <property name="textEncryptor">
 *      <ref bean="jasyptTextEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a PBEStringEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PBEStringEncryptor in several places,--> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" >
 *    <property name="algorithm" value="PBEWithMD5AndTripleDES" />
 *    <property name="password" value="myPassword" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PBEStringEncryptor instance so that it can be used from  -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.springsecurity4.crypto.password.PBEPasswordEncoder">
 *    <property name="pbeStringEncryptor">
 *      <ref bean="jasyptPBEStringEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class PBEPasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder { // The text encryptor or PBE string encryptor to be internally used private TextEncryptor textEncryptor = null; private PBEStringEncryptor pbeStringEncryptor = null; private Boolean useTextEncryptor = null; /** * Creates a new instance of PBEPasswordEncoder */ public PBEPasswordEncoder() { super(); } /** * Sets a text encryptor to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param textEncryptor the text encryptor instance to be used. */ public void setTextEncryptor(final TextEncryptor textEncryptor) { this.textEncryptor = textEncryptor; this.useTextEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setTextEncryptor or setPBEStringEncryptor should be * called. If both are, the last call will define which method will be * used. * * @param pbeStringEncryptor the PBE string encryptor instance to be used. */ public void setPbeStringEncryptor(final PBEStringEncryptor pbeStringEncryptor) { this.pbeStringEncryptor = pbeStringEncryptor; this.useTextEncryptor = Boolean.FALSE; } /** * Encodes a password. * * @param rawPassword The password to be encoded. */ public String encode(CharSequence rawPassword) { checkInitialization(); if (this.useTextEncryptor.booleanValue()) { return this.textEncryptor.encrypt(rawPassword.toString()); } return this.pbeStringEncryptor.encrypt(rawPassword.toString()); } /** * Checks a password's validity. * * @param encodedPassword The encrypted password against which to check. * @param rawPassword The password to be checked. */ public boolean matches(CharSequence rawPassword, String encodedPassword) { checkInitialization(); String decPassword = null; if (this.useTextEncryptor.booleanValue()) { decPassword = this.textEncryptor.decrypt(encodedPassword); } else { decPassword = this.pbeStringEncryptor.decrypt(encodedPassword); } if ((decPassword == null) || (rawPassword == null)) { return (decPassword == rawPassword); } return decPassword.equals(rawPassword); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a text encryptor or a PBE string encryptor has been set). */ private synchronized void checkInitialization() { if (this.useTextEncryptor == null) { this.textEncryptor = new BasicTextEncryptor(); this.useTextEncryptor = Boolean.TRUE; } else { if (this.useTextEncryptor.booleanValue()) { if (this.textEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: text " + "encryptor is null"); } } else { if (this.pbeStringEncryptor == null) { throw new EncryptionInitializationException( "PBE Password encoder not initialized: PBE " + "string encryptor is null"); } } } } } PasswordEncoder.java000066400000000000000000000205011360667575700400430ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-springsecurity4/src/main/java/org/jasypt/springsecurity4/crypto/password/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.springsecurity4.crypto.password; import org.jasypt.digest.StringDigester; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.util.password.BasicPasswordEncryptor; import org.jasypt.util.password.PasswordEncryptor; /** *

* This class implements the Spring Security 4.x * org.springframework.security.crypto.password.PasswordEncoder * interface, allowing Spring Security-enabled applications to use JASYPT * for password encryption. *

*

* Objects of this class will internally hold either an object of type * org.jasypt.util.password.PasswordEncryptor or an object of type * org.jasypt.digest.StringDigester (only one of them), * which should be set by respectively calling * {@link #setPasswordEncryptor(PasswordEncryptor)} or * {@link #setStringDigester(StringDigester)} * after creation. If neither a PasswordEncryptor nor * a StringDigester are set, a new * org.jasypt.util.password.BasicPasswordEncryptor object is * created and internally used. *

*

* Usage with a PasswordEncryptor *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the PasswordEncryptor in several places, --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptPasswordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the PasswordEncryptor instance so that it can be used from   -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.springsecurity4.springsecurity4.crypto.password.PasswordEncoder">
 *    <property name="passwordEncryptor">
 *      <ref bean="jasyptPasswordEncryptor" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* Usage with a StringDigester *

*

* This class can be used like this from your Spring XML resource files: *

*
 *  ...
 *  <!-- Your application may use the StringDigester in several places,    --> 
 *  <!-- like for example at new user sign-up.                             --> 
 *  <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
 *    <property name="algorithm" value="SHA-1" />
 *    <property name="iterations" value="100000" />
 *  </bean>
 *  ...
 *  ...
 *  <!-- This Spring Security-friendly PasswordEncoder implementation will -->
 *  <!-- wrap the StringDigester instance so that it can be used from      -->
 *  <!-- the security framework.                                           -->
 *  <bean id="passwordEncoder" class="org.jasypt.springsecurity4.crypto.password.PasswordEncoder">
 *    <property name="stringDigester">
 *      <ref bean="jasyptStringDigester" />
 *    </property>
 *  </bean>
 *  ...
 *  ...
 *  <!-- Your DaoAuthenticationProvider will then use it like with any     -->
 *  <!-- other implementation of the PasswordEncoder interface.            -->
 *  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 *      <property name="userDetailsService" ref="userDetailsService"/>
 *      <property name="passwordEncoder">
 *        <ref bean="passwordEncoder" />
 *      </property>
 *  </bean>
 *  ...
 * 
*

* This class is thread-safe *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder { // The password encryptor or string digester to be internally used private PasswordEncryptor passwordEncryptor = null; private StringDigester stringDigester = null; private Boolean useEncryptor = null; /** * Creates a new instance of PasswordEncoder */ public PasswordEncoder() { super(); } /** * Sets a password encryptor to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param passwordEncryptor the password encryptor instance to be used. */ public void setPasswordEncryptor(final PasswordEncryptor passwordEncryptor) { this.passwordEncryptor = passwordEncryptor; this.useEncryptor = Boolean.TRUE; } /** * Sets a string digester to be used. Only one of * setPasswordEncryptor or setStringDigester should be * called. If both are, the last call will define which method will be * used. * * @param stringDigester the string digester instance to be used. */ public void setStringDigester(final StringDigester stringDigester) { this.stringDigester = stringDigester; this.useEncryptor = Boolean.FALSE; } /** * Encodes a password. * * @param rawPassword The password to be encoded. */ public String encode(CharSequence rawPassword) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.encryptPassword(rawPassword.toString()); } return this.stringDigester.digest(rawPassword.toString()); } /** * Checks a password's validity. * * @param encodedPassword The encrypted password (digest) against which to check. * @param rawPassword The password to be checked. */ public boolean matches(CharSequence rawPassword, String encodedPassword) { checkInitialization(); if (this.useEncryptor.booleanValue()) { return this.passwordEncryptor.checkPassword(rawPassword.toString(), encodedPassword); } return this.stringDigester.matches(rawPassword.toString(), encodedPassword); } /* * Checks that the PasswordEncoder has been correctly initialized * (either a password encryptor or a string digester has been set). */ private synchronized void checkInitialization() { if (this.useEncryptor == null) { this.passwordEncryptor = new BasicPasswordEncryptor(); this.useEncryptor = Boolean.TRUE; } else { if (this.useEncryptor.booleanValue()) { if (this.passwordEncryptor == null) { throw new EncryptionInitializationException( "Password encoder not initialized: password " + "encryptor is null"); } } else { if (this.stringDigester == null) { throw new EncryptionInitializationException( "Password encoder not initialized: string " + "digester is null"); } } } } } jasypt-jasypt-1.9.3/jasypt-wicket13/000077500000000000000000000000001360667575700173365ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/.gitignore000066400000000000000000000000721360667575700213250ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-wicket13/BUILD.txt000066400000000000000000000014631360667575700207420ustar00rootroot00000000000000 Building JASYPT-WICKET13 ------------------------ To build JASYPT-WICKET13 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-WICKET13 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-wicket13-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-wicket13/{version}/jasypt-wicket13-{version}.jar Generating Javadoc for JASYPT-WICKET13 -------------------------------------- If you wish to generate the javadoc for JASYPT-WICKET13, execute this from the JASYPT-WICKET13 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-wicket13/ChangeLog.txt000066400000000000000000000003331360667575700217250ustar00rootroot000000000000001.9.3 ===== - Deprecated in 1.9.3. This module will be removed in 2.0.0. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Extracted jasypt-wicket13 package from previous monolithic jasypt module. jasypt-jasypt-1.9.3/jasypt-wicket13/LICENSE.txt000066400000000000000000000261361360667575700211710ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-wicket13/NOTICE.txt000066400000000000000000000072671360667575700210740ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-wicket13/README.txt000066400000000000000000000006111360667575700210320ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-wicket13/RELEASING.txt000066400000000000000000000023061360667575700214110ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-wicket13/USAGE.txt000066400000000000000000000011761360667575700207500ustar00rootroot00000000000000 Using JASYPT-WICKET13 from Maven 2 ---------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-wicket13 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-wicket13/pom.xml000066400000000000000000000155011360667575700206550ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-wicket13 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.apache.wicket wicket 1.3.0 provided true jasypt-jasypt-1.9.3/jasypt-wicket13/src/000077500000000000000000000000001360667575700201255ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/000077500000000000000000000000001360667575700210515ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/000077500000000000000000000000001360667575700217725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/000077500000000000000000000000001360667575700225615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/000077500000000000000000000000001360667575700240735ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket/000077500000000000000000000000001360667575700253615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket/JasyptCrypt.java000066400000000000000000000074571360667575700305350ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.util.crypt.Base64UrlSafe; import org.apache.wicket.util.crypt.ICrypt; import org.jasypt.encryption.pbe.PBEByteEncryptor; /** *

* Jasypt's implementation of {@link ICrypt}, based on the use of a * {@link PBEByteEncryptor} object for encryption and decryption operations. *

*

* This class is thread-safe. *

* * @since 1.4 * @author Daniel Fernández * @deprecated Package renamed to org.jasypt.wicket13. This class * will be removed in 1.11. Use {@link org.jasypt.wicket13.JasyptCrypt} * instead. * */ public final class JasyptCrypt implements ICrypt { // Encoding used to convert java String from and to byte[] private static final String CHARACTER_ENCODING = "UTF-8"; // The wrapped encryptor private final PBEByteEncryptor encryptor; /** *

* Creates a new JasyptCrypt object, wrapping the passed * encryptor. *

* * @param encryptor the PBEByteEncryptor to be used internally. */ public JasyptCrypt(final PBEByteEncryptor encryptor) { this.encryptor = encryptor; } /** *

* Decrypts a string using URL and filename safe Base64 decoding. *

* * @param text the text to be decrypted. * @return the decrypted string. */ public String decryptUrlSafe(final String text) { try { final byte[] base64EncryptedBytes = text.getBytes(); final byte[] encryptedBytes = Base64UrlSafe.decodeBase64(base64EncryptedBytes); return new String( this.encryptor.decrypt(encryptedBytes), CHARACTER_ENCODING); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Encrypts a string using URL and filename safe Base64 encoding. *

* * @param plainText the text to be encrypted. * @return encrypted string. */ public String encryptUrlSafe(final String plainText) { try { final byte[] plainBytes = plainText.getBytes(CHARACTER_ENCODING); final byte[] encryptedBytes = this.encryptor.encrypt(plainBytes); return new String(Base64UrlSafe.encodeBase64(encryptedBytes)); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Important: Using jasypt, it makes no sense to change the encryption * key once the encryptor has been initialized, and so this method is * implemented to throw UnsupportedOperationException always. *

*/ public void setKey(final String key) { throw new UnsupportedOperationException( "JasyptCrypt encryptors cannot be set password by calling " + ICrypt.class.getName() + ".setKey()"); } } jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket/JasyptCryptFactory.java000066400000000000000000000064171360667575700320600ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket; import org.apache.wicket.util.crypt.ICrypt; import org.apache.wicket.util.crypt.ICryptFactory; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.slf4j.LoggerFactory; /** *

* Implementation of the Apache Wicket {@link ICryptFactory} interface * which returns {@link JasyptCrypt} instances. *

*

* Requires a {@link PBEByteEncryptor} as a constructor argument, which can * be created or retrieved from any part of the jasypt encryption configuration * infrastructure. *

*

* *

*

* This class is thread-safe. *

* * @since 1.4 * @author Daniel Fernández * @deprecated Package renamed to org.jasypt.wicket13. This class * will be removed in 1.11. Use {@link org.jasypt.wicket13.JasyptCrypt} * instead. * */ public final class JasyptCryptFactory implements ICryptFactory { // Encryptor doesn't need to be instanced each time. We hold a reference. private final JasyptCrypt jasyptCrypt; /** *

* Creates a new instance of JasyptCryptFactory. *

*

* This factory uses an instance of {@link PBEByteEncryptor} instead of * a {@link PBEStringEncryptor} (as could be expected) because Wicket * requires a specific type of String encoding (URL and file safe * BASE64), which is managed by a wicket internal class, and which * expectes byte[] input. *

* * @param encryptor the PBEByteEncryptor to be used. */ public JasyptCryptFactory(final PBEByteEncryptor encryptor) { this.jasyptCrypt = new JasyptCrypt(encryptor); LoggerFactory.getLogger(JasyptCryptFactory.class).warn( "The org.jasypt.wicket.JasyptCryptFactory and " + "org.jasypt.wicket.JasyptCrypt classes from the " + "jasypt-wicket13 package class have been moved to package " + "org.jasypt.wicket13. The old class names have been " + "DEPRECATED. Please update your package names before " + "these classes are deleted in future versions"); } /** *

* Return a new encryptor object. *

*

* This method returns always the same JasyptCrypt object, instead * of creating a new one. *

*/ public ICrypt newCrypt() { return this.jasyptCrypt; } } jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket13/000077500000000000000000000000001360667575700255255ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket13/JasyptCrypt.java000066400000000000000000000074431360667575700306740ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket13; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.util.crypt.Base64UrlSafe; import org.apache.wicket.util.crypt.ICrypt; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.salt.ByteArrayFixedSaltGenerator; import org.jasypt.salt.FixedSaltGenerator; /** *

* Jasypt's implementation of {@link ICrypt}, based on the use of a * {@link PBEByteEncryptor} object for encryption and decryption operations. *

*

* This class is thread-safe. *

* * @since 1.9.0 * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class JasyptCrypt implements ICrypt { // Encoding used to convert java String from and to byte[] private static final String CHARACTER_ENCODING = "UTF-8"; // The wrapped encryptor private final PBEByteEncryptor encryptor; /** *

* Creates a new JasyptCrypt object, wrapping the passed * encryptor. *

* * @param encryptor the PBEByteEncryptor to be used internally. */ public JasyptCrypt(final PBEByteEncryptor encryptor) { this.encryptor = encryptor; } /** *

* Decrypts a string using URL and filename safe Base64 decoding. *

* * @param text the text to be decrypted. * @return the decrypted string. */ public String decryptUrlSafe(final String text) { try { final byte[] base64EncryptedBytes = text.getBytes(); final byte[] encryptedBytes = Base64UrlSafe.decodeBase64(base64EncryptedBytes); return new String( this.encryptor.decrypt(encryptedBytes), CHARACTER_ENCODING); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Encrypts a string using URL and filename safe Base64 encoding. *

* * @param plainText the text to be encrypted. * @return encrypted string. */ public String encryptUrlSafe(final String plainText) { try { final byte[] plainBytes = plainText.getBytes(CHARACTER_ENCODING); final byte[] encryptedBytes = this.encryptor.encrypt(plainBytes); return new String(Base64UrlSafe.encodeBase64(encryptedBytes)); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Important: Using jasypt, it makes no sense to change the encryption * key once the encryptor has been initialized, and so this method is * implemented to throw UnsupportedOperationException always. *

*/ public void setKey(final String key) { throw new UnsupportedOperationException( "JasyptCrypt encryptors cannot be set password by calling " + ICrypt.class.getName() + ".setKey()"); } } jasypt-jasypt-1.9.3/jasypt-wicket13/src/main/java/org/jasypt/wicket13/JasyptCryptFactory.java000066400000000000000000000052361360667575700322220ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket13; import org.apache.wicket.util.crypt.ICrypt; import org.apache.wicket.util.crypt.ICryptFactory; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Implementation of the Apache Wicket {@link ICryptFactory} interface * which returns {@link JasyptCrypt} instances. *

*

* Requires a {@link PBEByteEncryptor} as a constructor argument, which can * be created or retrieved from any part of the jasypt encryption configuration * infrastructure. *

*

* *

*

* This class is thread-safe. *

* * @since 1.9.0 * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class JasyptCryptFactory implements ICryptFactory { // Encryptor doesn't need to be instanced each time. We hold a reference. private final JasyptCrypt jasyptCrypt; /** *

* Creates a new instance of JasyptCryptFactory. *

*

* This factory uses an instance of {@link PBEByteEncryptor} instead of * a {@link PBEStringEncryptor} (as could be expected) because Wicket * requires a specific type of String encoding (URL and file safe * BASE64), which is managed by a wicket internal class, and which * expectes byte[] input. *

* * @param encryptor the PBEByteEncryptor to be used. */ public JasyptCryptFactory(final PBEByteEncryptor encryptor) { this.jasyptCrypt = new JasyptCrypt(encryptor); } /** *

* Return a new encryptor object. *

*

* This method returns always the same JasyptCrypt object, instead * of creating a new one. *

*/ public ICrypt newCrypt() { return this.jasyptCrypt; } } jasypt-jasypt-1.9.3/jasypt-wicket15/000077500000000000000000000000001360667575700173405ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/.gitignore000066400000000000000000000000721360667575700213270ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt-wicket15/BUILD.txt000066400000000000000000000014631360667575700207440ustar00rootroot00000000000000 Building JASYPT-WICKET15 ------------------------ To build JASYPT-WICKET15 you will need Maven 2. You can get it at: http://maven.apache.org Build and install the project executing, from the JASYPT-WICKET15 project root folder: mvn clean:clean install And you will get a fresh target/jasypt-wicket15-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt-wicket15/{version}/jasypt-wicket15-{version}.jar Generating Javadoc for JASYPT-WICKET15 -------------------------------------- If you wish to generate the javadoc for JASYPT-WICKET15, execute this from the JASYPT-WICKET15 root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt-wicket15/ChangeLog.txt000066400000000000000000000003521360667575700217300ustar00rootroot000000000000001.9.3 ===== - Deprecated in 1.9.3. This module will be removed in 2.0.0. 1.9.2 ===== (no changes) 1.9.1 ===== (no changes) 1.9.0 ===== - Created jasypt-wicket15 module, enabling compatibility with version 1.5 of Apache Wicket. jasypt-jasypt-1.9.3/jasypt-wicket15/LICENSE.txt000066400000000000000000000261361360667575700211730ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt-wicket15/NOTICE.txt000066400000000000000000000072671360667575700210760ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt-wicket15/README.txt000066400000000000000000000006111360667575700210340ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt-wicket15/RELEASING.txt000066400000000000000000000023061360667575700214130ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt-wicket15/USAGE.txt000066400000000000000000000011761360667575700207520ustar00rootroot00000000000000 Using JASYPT-WICKET15 from Maven 2 ---------------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt-wicket15 {version} compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt-wicket15/pom.xml000066400000000000000000000154501360667575700206620ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt-wicket15 jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.0 none protected java.lang org.jasypt.contrib.* http://www.jasypt.org/api/jasypt/${project.version}/ package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-release-plugin 2.5.3 true org.jasypt jasypt 1.9.3 compile org.apache.wicket wicket-core 1.5.0 provided true jasypt-jasypt-1.9.3/jasypt-wicket15/src/000077500000000000000000000000001360667575700201275ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/000077500000000000000000000000001360667575700210535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/000077500000000000000000000000001360667575700217745ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/org/000077500000000000000000000000001360667575700225635ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/org/jasypt/000077500000000000000000000000001360667575700240755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/org/jasypt/wicket15/000077500000000000000000000000001360667575700255315ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/org/jasypt/wicket15/JasyptCrypt.java000066400000000000000000000072571360667575700307030ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket15; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.util.crypt.Base64; import org.apache.wicket.util.crypt.ICrypt; import org.jasypt.encryption.pbe.PBEByteEncryptor; /** *

* Jasypt's implementation of {@link ICrypt}, based on the use of a * {@link PBEByteEncryptor} object for encryption and decryption operations. *

*

* This class is thread-safe. *

* * @since 1.9.0 * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class JasyptCrypt implements ICrypt { // Encoding used to convert java String from and to byte[] private static final String CHARACTER_ENCODING = "UTF-8"; // The wrapped encryptor private final PBEByteEncryptor encryptor; /** *

* Creates a new JasyptCrypt object, wrapping the passed * encryptor. *

* * @param encryptor the PBEByteEncryptor to be used internally. */ public JasyptCrypt(final PBEByteEncryptor encryptor) { this.encryptor = encryptor; } /** *

* Decrypts a string using URL and filename safe Base64 decoding. *

* * @param text the text to be decrypted. * @return the decrypted string. */ public String decryptUrlSafe(final String text) { try { final byte[] base64EncryptedBytes = text.getBytes(); final byte[] encryptedBytes = Base64.decodeBase64(base64EncryptedBytes); return new String( this.encryptor.decrypt(encryptedBytes), CHARACTER_ENCODING); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Encrypts a string using URL and filename safe Base64 encoding. *

* * @param plainText the text to be encrypted. * @return encrypted string. */ public String encryptUrlSafe(final String plainText) { try { final byte[] plainBytes = plainText.getBytes(CHARACTER_ENCODING); final byte[] encryptedBytes = this.encryptor.encrypt(plainBytes); return new String(Base64.encodeBase64(encryptedBytes)); } catch (Exception e) { throw new WicketRuntimeException(e); } } /** *

* Important: Using jasypt, it makes no sense to change the encryption * key once the encryptor has been initialized, and so this method is * implemented to throw UnsupportedOperationException always. *

*/ public void setKey(final String key) { throw new UnsupportedOperationException( "JasyptCrypt encryptors cannot be set password by calling " + ICrypt.class.getName() + ".setKey()"); } } jasypt-jasypt-1.9.3/jasypt-wicket15/src/main/java/org/jasypt/wicket15/JasyptCryptFactory.java000066400000000000000000000052361360667575700322260ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.wicket15; import org.apache.wicket.util.crypt.ICrypt; import org.apache.wicket.util.crypt.ICryptFactory; import org.jasypt.encryption.pbe.PBEByteEncryptor; import org.jasypt.encryption.pbe.PBEStringEncryptor; /** *

* Implementation of the Apache Wicket {@link ICryptFactory} interface * which returns {@link JasyptCrypt} instances. *

*

* Requires a {@link PBEByteEncryptor} as a constructor argument, which can * be created or retrieved from any part of the jasypt encryption configuration * infrastructure. *

*

* *

*

* This class is thread-safe. *

* * @since 1.9.0 * @author Daniel Fernández * @deprecated Deprecated in 1.9.3. This class will be removed in 2.0.0. * */ public final class JasyptCryptFactory implements ICryptFactory { // Encryptor doesn't need to be instanced each time. We hold a reference. private final JasyptCrypt jasyptCrypt; /** *

* Creates a new instance of JasyptCryptFactory. *

*

* This factory uses an instance of {@link PBEByteEncryptor} instead of * a {@link PBEStringEncryptor} (as could be expected) because Wicket * requires a specific type of String encoding (URL and file safe * BASE64), which is managed by a wicket internal class, and which * expectes byte[] input. *

* * @param encryptor the PBEByteEncryptor to be used. */ public JasyptCryptFactory(final PBEByteEncryptor encryptor) { this.jasyptCrypt = new JasyptCrypt(encryptor); } /** *

* Return a new encryptor object. *

*

* This method returns always the same JasyptCrypt object, instead * of creating a new one. *

*/ public ICrypt newCrypt() { return this.jasyptCrypt; } } jasypt-jasypt-1.9.3/jasypt/000077500000000000000000000000001360667575700157065ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/.gitignore000066400000000000000000000000721360667575700176750ustar00rootroot00000000000000.classpath .project target/ bin/ .settings/ .idea/ *.iml jasypt-jasypt-1.9.3/jasypt/BUILD.txt000066400000000000000000000015721360667575700173130ustar00rootroot00000000000000 Building JASYPT --------------- To build JASYPT you will need Maven 2. You can get it at: http://maven.apache.org Also, in order to pass the unit tests, you will need the Java Unlimited Jurisdiction Policy files installed for the JDK with which you are going to do the build. Build and install the project executing, from the JASYPT project root folder: mvn clean:clean install And you will get a fresh target/jasypt-{version}.jar file. You will also get it installed in your local repository at: $M2_REPO/org/jasypt/jasypt/{version}/jasypt-{version}.jar Generating Javadoc for JASYPT ----------------------------- If you wish to generate the javadoc for JASYPT, execute this from the JASYPT root folder: mvn javadoc:javadoc This will generate the javadoc documentation in HTML format in: target/site/apidocs jasypt-jasypt-1.9.3/jasypt/ChangeLog.txt000066400000000000000000000363071360667575700203070ustar00rootroot000000000000001.9.3 ===== - Fixed #44: Using Standard PBE Encryptors for BigDecimal or BigInteger causes unnecessary exception on VMs with large amounts of freespace - Fixed #32: encryption works but decryption does not, Java 8 (JCE jars installed). Added support for initialization vectors needed for AES encryption and decryption since Java 8. 1.9.2 ===== - Replaced Arrays.equals() call in StandardByteDigester with a time-constant function in order to enhance protection against timing attacks in unintended scenarios where parts of jasypt are used for matching message-authentication hashes. Note: password matching and general hash matching scenarios using jasypt were NOT affected by vulnerabilities to timing attacks. - Modified how the EncryptableProperties objects deal with serialization, so that now they only make use of the singleton encryptor registry when they are actually serialized (if they are). This allows the removal of the "finalize()" method in this objects, which was causing trouble in some specific Java VM setups. - Created new interface org.jasypt.salt.FixedSaltGenerator and two new implementations for it, org.jasypt.salt.StringFixedSaltGenerator and org.jasypt.salt.ByteArrayFixedSaltGenerator, deprecating old equivalents "FixedStringSaltGenerator" and "FixedByteArraySaltGenerator". This new interface allows applying important performance optimizations to encryption operations when using fixed salt. - Modified UTF-8 normalization infrastructure in order to make code compile in Java 1.4. - Updated testing-scope dependencies. 1.9.1 ===== - Fixed insufficient entropy in RandomSaltGenerator due to seeding mechanism. - Fixed CLI scripts for Windows and CYGWIN environments. 1.9.0 ===== - Divided old "jasypt" artifact into several modules: * jasypt (core) * jasypt-hibernate3 * jasypt-hibernate4 * jasypt-spring2 * jasypt-spring3 * jasypt-acegisecurity * jasypt-springsecurity2 * jasypt-springsecurity3 * jasypt-wicket13 * jasypt-wicket15 - Fixed error in CLI .bat files resulting in bad processing of CLI commands which involved passwords containing exclamation mark symbols. - Fixed bug in PooledPBEStringEncryptor which caused first encryptor in pool not use hexadecimal output type. - Added implementation of Hashtable's "get(Object)" method to org.jasypt.properties.EncryptableProperties, so that this method now performs decryption instead of it only being performed at "getProperty(key)". 1.8 === - Small bugfixing for large BigInteger number decryption. - Modified in-memory storage of PBE passwords to avoid having Strings in memory that contain the password being used. Now PBE passwords are stored as char[] objects that are zeroed as soon as they are used. New "setPasswordCharArray(char[] password)" methods allow users to specify passwords as char[] also, so that there is no need to create String passwords. - Modified the order in which Normalizer implementations are used: now icu4j is used if it is in the classpath (even if Java >= 6 is being used). If icu4j is not present, java.text.Normalizer is used (if Java >= 6). - Fixed CLI scripts: *.jar in "find" command was matching jar files in the current folder instead of those in the lib folder. Fixed by surrounding "*.jar" by simple inverted commas. - Added to EncryptablePropertyPlaceholderConfigurer the ability to decrypt system properties. 1.7.1 ===== - Fixed EncryptableServletContextPropertyPlaceholderConfigurer 1.7 === - Fixed Hibernate 3.6 compatibility. - Removed dependencies on commons-lang and commons-codec. Jasypt can now operate without depedencies on JDK version >= 6. - Added pool-based implementations of Standard digesters and PBE encryptors to improve performance in multiprocessor systems. - Created "lite" .jar package including only standard String and Byte digest and encryption: no BigDecimal or BigInteger encryption, no "util" package, no Spring/Hibernate/Wicket integrations, no Web PBE configuration, no CLI utils, no properties encryption, no Zero salt generator. - Added class org.jasypt.registry.AlgorithmRegistry with utility methods for obtaining the names of all the available digest/PBE algorithms. - Added "prefix" and "suffix" configuration parameters to String digesters, in order to add a prefix and/or suffix to all digest results (and also expect these prefixes or suffixes when matching existing digests). - Added method "getInvertPositionOfSaltInMessageBeforeDigesting()" to DigesterConfig and "setInvertPositionOfSaltInMessageBeforeDigesting(...)" to StandardByteDigester and StandardStringDigester in order to being able to append the salt after the message before digesting instead of the default behaviour (insert it before the message). This is useful for enhancing compatibility with some common LDAP password encryption schemes like {SSHA}. - Added method "getInvertPositionOfPlainSaltInEncryptionResults()" to DigesterConfig and "setInvertPositionOfPlainSaltInEncryptionResults(...)" to StandardByteDigester and StandardStringDigester in order to being able to append the plain (unhashed) salt after the digest instead of the default behaviour (insert it before the digest). This is useful for enhancing compatibility with some common LDAP password encryption schemes like {SSHA}. - Added method "getUseLenientSaltSizeCheck()" to DigesterConfig and "setUseLenientSaltSizeCheck(...)" to StandardByteDigester and StandardStringDigester in order to allow digesters to check digests created with any size of salt (not equal to the value set for the "saltSizeBytes" property). - Added an "org.jasypt.util.password.rfc2307" package containing utility classes for password encryption operations according to common LDAP schemes like {MD5}, {SHA}, {SMD5} and {SSHA}. - Rebuilt CLI scripts: now both Windows and Linux versions can be run from outside the "bin" folder. New configuration parameters added. - Added "listAlgorithms" CLI command that lists all digest and PBE algorithms present in the Java Virtual Machine. - Rebuilt zip distribution package: remove unneeded "cli-bundle" and added icu4j to libs. - Added org.jasypt.spring.properties.EncryptableServletContextPropertyPlaceholderConfigurer as a sublass of org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer, for transparent decryption of servlet context parameters (like the ones in web.xml). - Added org.jasypt.spring.properties.EncryptablePreferencesPlaceholderConfigurer as a subclass of org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer, for transparent decryption of preferences set with JDK 1.4's Preferences API. - Added Spring Security 3 -compatible TokenBasedRememberMeServices implementation using a Jasypt StandardStringDigester for digesting the data signature. 1.6 === - Modified Class.forName calls to use current thread's context classloader. - Fixed JavaDoc for Spring Security -related classes. - Added missing registerPBE*Encryptor methods in HibernatePBEEncryptorRegistry - Added compatibility with Spring Framework 3.0.x and Spring Security 3.0.x - Tested compatibility with Apache Wicket 1.4.x and Hibernate 3.2.x 1.5 === - Dependency on ICU4j made optional in Java 6 environments. - Created new versions of old ACEGI's PasswordEncoder and PBEPasswordEncoder for Spring Security 2.x in package org.jasypt.spring.security2. - Random number generation algorithm can now be specified in RandomSaltGenerator. - Fixed bug in .sh files in the bin folder. $@ did not work with inputs that contained spaces and had to be substituted by "$@". 1.4.1 ======= - Fixed bug in EncryptedPasswordC3P0ConnectionProvider which made decryption of datasource configuration not to work properly. 1.4 ======= - Added methods to Simple* and Environment* config classes for both Digesters and PBEEncryptors to allow them to be configured entirely with Strings. - Added to org.jasypt.encryption.pbe.StandardPBEByteEncryptor a workaround for Sun JCE's bug 4953555 (http://bugs.sun.com/view_bug.do?bug_id=4953555) - Added org.jasypt.properties.EncryptableProperties as a java.util.Properties which allows transparent decryption of encrypted property values. - Moved org.jasypt.hibernate.ParameterNaming to org.jasypt.hibernate.type.ParameterNaming. - Added org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider and org.jasypt.hibernate.connectionprovider.EncryptedPasswordC3P0ConnectionProvider for allowing encrypted datasource parameters in hibernate.cfg.xml files. - Added org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer and org.jasypt.spring.properties.EncryptablePropertyOverrideConfigurer to allow use of encrypted .properties files from within Spring applications in a transparent manner. - Package org.jasypt.springsecurity renamed as org.jasypt.spring.security, and deprecated classes in the old package (will be removed in 1.5). - Added org.jasypt.salt.ZeroSaltGenerator for creating salts filled with "zero" bytes. - Added org.jasypt.intf.service.JasyptStatelessService for supporting CLI operation and development of stateless services (like web services) for Jasypt. - Added org.jasypt.intf.cli.JasyptStringDigestCLI, org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI and org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI to allow the execution of digest, encryption and decryption commands from the command line, useful for knowing which value to write in an encrypted .properties file. - Created new zip distribution containing convenience .sh and .bat files for executing CLI tools. 1.3.1 ======= - Solved configuration bug in "StandardPBEByteEncryptor.initialize()" for algorithms coming from *Config objects. 1.3 ======= - DigesterConfig and PBEConfig are not Serializable anymore. - Added provider and providerName properties to DigesterConfig and SimpleDigesterConfig classes. - Added providerClassName, providerName and saltGeneratorClassName configuration at EnvironmentDigesterConfig. - StandardByteDigester, StandardStringDigester, Digester, and ConfigurablePasswordEncryptor can now specify the JCE security provider (java.security.Provider implementation) which will be asked for the digest algorithm. - Added provider and providerName properties to PBEConfig and SimplePBEConfig classes. - Added providerClassName, providerName and saltGeneratorClassName configuration at EnvironmentPBEConfig. - StandardPBEByteEncryptor, StandardPBEStringEncryptor, StandardPBEBigIntegerEncryptor and StandardPBEBigDecimalEncryptor can now specify the JCE security provider (java.security.Provider implementation) which will be asked for the digest algorithm. - Created new StringDigesterConfig configuration interface for digesters, which extends DigesterConfig and adds parameters "unicodeNormalizationIgnored" and "stringOutputType". Also created new implementations SimpleStringDigesterConfig and EnvironmentStringDigesterConfig. - Added Unicode Normalization step to StandardStringDigester, and also capabilities to return hexadecimal-encoded digest Strings instead of only BASE64 ones. - Created new StringPBEConfig configuration interface for encryptors, which extends PBEConfig and adds parameter "stringOutputType". Also created new implementations SimpleStringPBEConfig and EnvironmentStringPBEConfig. - Added capabilities to return hexadecimal-endoded Strings to StandardPBEStringEncryptor. - Added capabilities to return hexadecimal-endoded Strings to ConfigurablePasswordEncryptor. - Added to HibernatePBEStringEncryptor the possibility to set the providerName, provider and stringOutputType parameters. - Added providerName and stringOutputType parameters to all the String-related Hibernate types. - Added package org.jasypt.web.pbeconfig for configuration of PBE encryption keys from webapps. Includes servlet, filter and contextlistener. - Added WebPBEConfig and WebStringPBEConfig for configuration through the new web PBE config infrastructure. 1.2 ======= - Merged jasypt-hibernate and jasypt-spring-security into main jasypt trunk. - Package org.jasypt.util refactored. - Created PasswordEncryptor and TextEncryptor interfaces, to unify both basic- and strong-encryption implementations. NOTE: the old org.jasypt.util classes have been DEPRECATED, and will be removed in jasypt 1.3. - Added org.jasypt.util.password.ConfigurablePasswordEncryptor for a more configurable way of using the "easy" password encryptor. - Added binary utils (org.jasypt.util.binary) for easy encryption of binaries. - Added numeric encryption functionalities: new StandardPBEBigIntegerEncryptor and StandardPBEBigDecimalEncryptor in the org.jasypt.encryption.pbe package - Added new org.jasypt.util.numeric package with easy utils for numeric encryption. - Refactored org.jasypt.hibernate classes into new "encryptor" and "type" subpackages. - Added HibernatePBEEncryptorRegistry support for BigInteger, BigDecimal and Byte encryptors - Added Hibernate type for encryption of binaries (byte[]) into SQL BLOBs - Added Hibernate type for encryption of BigIntegers into SQL NUMERICs. - Added Hibernate type for encryption of BigDecimals into SQL NUMERICs. - Added Hibernate type for encryption of Bytes into SQL VARCHARs. - Added Hibernate type for encryption of Shorts into SQL VARCHARs. - Added Hibernate type for encryption of Integers into SQL VARCHARs. - Added Hibernate type for encryption of Longs into SQL VARCHARs. - Added Hibernate type for encryption of Floats into SQL VARCHARs. - Added Hibernate type for encryption of Doubles into SQL VARCHARs. - Added Hibernate type for encryption of Booleans into SQL VARCHARs. - Added Hibernate type for encryption of Dates into SQL VARCHARs. - Added Hibernate type for encryption of Calendars into SQL VARCHARs. - Added creation of standard encryptor in Hibernate encryptor objects so that setEncryptor() method becomes optional and hibernate encryptors can be directly configured via setPassword, setAlgorithm, etc. - Refactored org.jasypt.springsecurity package: created new PasswordEncoder for use with both org.jasypt.util.password.PasswordEncryptor or org.jasypt.digest.StringDigester implementations. - Created new org.jasypt.springsecurity.PBEPasswordEncoder for using org.jasypt.util.text.TextEncryptor or org.jasypt.pbe.encryptor.PBEStringEncryptor from ACEGI Security. - Created new salt generation infrastructure, making different implementations of salt generation possible (including fixed salt). 1.1 ======= - Added the ACEGI (Spring Security) integration add-on (org.jasypt.springsecurity) - Added org.jasypt.util.StrongPasswordEncryptor as a util class for easy password encryption using a stronger algorithm. - Added org.jasypt.util.MessageDigester as a util class for creating simple binary message digests. - Added org.jasypt.digest.config.EnvironmentDigesterConfig and org.jasypt.encryption.pbe.config.EnvironmentPBEConfig for configuration of encryptors and digesters using environment variables and system properties. - Objects of class org.jasypt.util.PasswordEncryptor now initialize their internal StandardStringDigester at instance creation. - Made org.jasypt.digest.config.DigesterConfig and org.jasypt.encryption.pbe.config.PBEConfig extend java.io.Serializable 1.0 ======= - First release of jasypt jasypt-jasypt-1.9.3/jasypt/LICENSE.txt000066400000000000000000000261361360667575700175410ustar00rootroot00000000000000 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. jasypt-jasypt-1.9.3/jasypt/NOTICE.txt000066400000000000000000000072671360667575700174440ustar00rootroot00000000000000 Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) 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. --------------------------------- This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the cryptographic software used (note that this software is not included in the distribution): * The PBE Encryption facilities require the Java Cryptography extensions: http://java.sun.com/javase/technologies/security/. --------------------------------- Distributions of this software may include software developed by The Apache Software Foundation (http://www.apache.org/). --------------------------------- ICU License - ICU 1.8.1 and later COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2006 International Business Machines Corporation and others All rights reserved. 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, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. 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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. jasypt-jasypt-1.9.3/jasypt/README.txt000066400000000000000000000006111360667575700174020ustar00rootroot00000000000000 JASYPT: Java Simplified Encryption ---------------------------------- Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. To learn more and download latest version: http://www.jasypt.org jasypt-jasypt-1.9.3/jasypt/RELEASING.txt000066400000000000000000000023061360667575700177610ustar00rootroot00000000000000In order to prepare a release, this steps have to be taken: 1. In settings.xml, these entries must exist: releases [KEYNAME (EMAIL)] [GPG PASSPHRASE] sonatype-nexus-snapshots [USER IN SONATYPE NEXUS] [PASSWORD IN SONATYPE NEXUS] 2. Ensure all SVN URLs in pom.xml are using "https". A "502 Bad Gateway" error will be received if not. 3. Deploy SNAPSHOT artifact to Sonatype NEXUS with "mvn deploy", and check in Nexus web interface. 4. Execute a test "no modification" run of the release:prepare goal: "mvn -Preleases release:prepare -DdryRun=true -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 5. Execute a real run of the release:prepare goal: "mvn -Preleases release:prepare -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 6. Upload the release: "mvn -Preleases release:perform -Dusername=[SVNUSER] -Dpassword=[SVNPASS]" 7. Follow instructions for Nexus at: http://nexus.sonatype.org/oss-repository-hosting.html jasypt-jasypt-1.9.3/jasypt/USAGE.txt000066400000000000000000000016411360667575700173150ustar00rootroot00000000000000 Using JASYPT from Maven 2 ------------------------- In order to use it in your Maven 2 applications, you will need to add it as a dependency with: org.jasypt jasypt {version} compile Or, alternatively, you can use the "lite" artifact (see online docs) by specifying a classifier: org.jasypt jasypt {version} lite compile In order for this to work correctly, you need to have previously installed jasypt in your local repository (as explained in BUILD.txt) or have a working internet connection to let maven automatically download jasypt binaries from Maven 2's central repositories. jasypt-jasypt-1.9.3/jasypt/pom.xml000066400000000000000000000176721360667575700172400ustar00rootroot00000000000000 4.0.0 org.jasypt jasypt jar 1.9.3 JASYPT: Java Simplified Encryption http://www.jasypt.org Java library which enables encryption in java apps with minimum effort. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo The JASYPT team http://www.jasypt.org scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git scm:git:git@github.com:jasypt/jasypt.git HEAD dfernandez Daniel Fernandez dfernandez AT users.sourceforge.net Project admin sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots true src/main/resources . META-INF LICENSE.txt NOTICE.txt src/test/resources org.apache.maven.plugins maven-site-plugin 2.1 org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.6 1.6 US-ASCII org.apache.maven.plugins maven-resources-plugin 2.5 US-ASCII org.apache.maven.plugins maven-javadoc-plugin 3.0.1 none protected java.lang org.jasypt.contrib.* package jar org.apache.maven.plugins maven-source-plugin 2.1.2 package jar org.apache.maven.plugins maven-gpg-plugin 1.1 sign-artifacts verify sign org.apache.maven.plugins maven-assembly-plugin 2.2 src/assembly/lite.xml make-assembly-deps package single org.apache.maven.plugins maven-release-plugin 2.5.3 true com.ibm.icu icu4j 3.4.4 provided true javax.servlet servlet-api 2.4 provided true bouncycastle bcprov-jdk12 140 test junit junit 3.8.1 test commons-lang commons-lang 2.1 test jasypt-jasypt-1.9.3/jasypt/src/000077500000000000000000000000001360667575700164755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/assembly/000077500000000000000000000000001360667575700203145ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/assembly/lite.xml000066400000000000000000000037061360667575700220010ustar00rootroot00000000000000 lite jar false ${basedir}/target/classes org/jasypt/commons/**/* org/jasypt/contrib/**/* org/jasypt/digest/**/* org/jasypt/encryption/**/* org/jasypt/exceptions/**/* org/jasypt/normalization/**/* org/jasypt/salt/**/* org/jasypt/iv/**/* org/jasypt/encryption/pbe/config/WebPBEConfig.class org/jasypt/encryption/pbe/config/WebStringPBEConfig.class org/jasypt/encryption/pbe/PBEBigDecimalEncryptor.class org/jasypt/encryption/pbe/PBEBigIntegerEncryptor.class org/jasypt/encryption/pbe/StandardPBEBigDecimalEncryptor.class org/jasypt/encryption/pbe/StandardPBEBigIntegerEncryptor.class org/jasypt/encryption/pbe/PooledPBEBigDecimalEncryptor.class org/jasypt/encryption/pbe/PooledPBEBigIntegerEncryptor.class org/jasypt/encryption/BigDecimalEncryptor.class org/jasypt/encryption/BigIntegerEncryptor.class org/jasypt/salt/ZeroSaltGenerator.class jasypt-jasypt-1.9.3/jasypt/src/main/000077500000000000000000000000001360667575700174215ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/000077500000000000000000000000001360667575700203425ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/000077500000000000000000000000001360667575700211315ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/000077500000000000000000000000001360667575700224435ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/commons/000077500000000000000000000000001360667575700241165ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/commons/CommonUtils.java000066400000000000000000000211441360667575700272340ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.commons; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; /** *

* Common utils regarding treatment of parameter values and encoding operations. * This class is for internal use only. *

* * @since 1.3 * * @author Daniel Fernández * */ public final class CommonUtils { public static final String STRING_OUTPUT_TYPE_BASE64 = "base64"; public static final String STRING_OUTPUT_TYPE_HEXADECIMAL = "hexadecimal"; private static final List STRING_OUTPUT_TYPE_HEXADECIMAL_NAMES = Arrays.asList( new String[] { "HEXADECIMAL", "HEXA", "0X", "HEX", "HEXADEC" } ); private static char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; public static Boolean getStandardBooleanValue(final String valueStr) { if (valueStr == null) { return null; } final String upperValue = valueStr.toUpperCase(); if ("TRUE".equals(upperValue) || "ON".equals(upperValue) || "YES".equals(upperValue)) { return Boolean.TRUE; } if ("FALSE".equals(upperValue) || "OFF".equals(upperValue) || "NO".equals(upperValue)) { return Boolean.FALSE; } return null; } public static String getStandardStringOutputType(final String valueStr) { if (valueStr == null) { return null; } if (STRING_OUTPUT_TYPE_HEXADECIMAL_NAMES.contains(valueStr.toUpperCase())) { return STRING_OUTPUT_TYPE_HEXADECIMAL; } return STRING_OUTPUT_TYPE_BASE64; } public static String toHexadecimal(final byte[] message) { if (message == null) { return null; } final StringBuffer buffer = new StringBuffer(); for (int i = 0; i < message.length; i++) { int curByte = message[i] & 0xff; buffer.append(hexDigits[(curByte >> 4)]); buffer.append(hexDigits[curByte & 0xf]); } return buffer.toString(); } public static byte[] fromHexadecimal(final String message) { if (message == null) { return null; } if ((message.length() % 2) != 0) { throw new EncryptionOperationNotPossibleException(); } try { final byte[] result = new byte[message.length() / 2]; for (int i = 0; i < message.length(); i = i + 2) { final int first = Integer.parseInt("" + message.charAt(i), 16); final int second = Integer.parseInt("" + message.charAt(i + 1), 16); result[i/2] = (byte) (0x0 + ((first & 0xff) << 4) + (second & 0xff)); } return result; } catch (Exception e) { throw new EncryptionOperationNotPossibleException(); } } public static boolean isEmpty(final String string) { if (string == null || string.length() == 0) { return true; } return false; } public static boolean isNotEmpty(final String string) { if (string == null || string.length() == 0) { return false; } return true; } public static void validateNotNull(final Object object, final String message) { if (object == null) { throw new IllegalArgumentException(message); } } public static void validateNotEmpty(final String string, final String message) { if (isEmpty(string)) { throw new IllegalArgumentException(message); } } public static void validateIsTrue(final boolean expression, final String message) { if (expression == false) { throw new IllegalArgumentException(message); } } public static String[] split(final String string) { // Whitespace will be used as separator return split(string, null); } public static String[] split(final String string, final String separators) { if (string == null) { return null; } final int length = string.length(); if (length == 0) { return new String[0]; } final List results = new ArrayList(); int i = 0; int start = 0; boolean tokenInProgress = false; if (separators == null) { while (i < length) { if (Character.isWhitespace(string.charAt(i))) { if (tokenInProgress) { results.add(string.substring(start, i)); tokenInProgress = false; } start = ++i; continue; } tokenInProgress = true; i++; } } else if (separators.length() == 1) { final char separator = separators.charAt(0); while (i < length) { if (string.charAt(i) == separator) { if (tokenInProgress) { results.add(string.substring(start, i)); tokenInProgress = false; } start = ++i; continue; } tokenInProgress = true; i++; } } else { while (i < length) { if (separators.indexOf(string.charAt(i)) >= 0) { if (tokenInProgress) { results.add(string.substring(start, i)); tokenInProgress = false; } start = ++i; continue; } tokenInProgress = true; i++; } } if (tokenInProgress) { results.add(string.substring(start, i)); } return (String[]) results.toArray(new String[results.size()]); } public static String substringBefore(final String string, final String separator) { if (isEmpty(string) || separator == null) { return string; } if (separator.length() == 0) { return ""; } final int pos = string.indexOf(separator); if (pos == -1) { return string; } return string.substring(0, pos); } public static String substringAfter(final String string, final String separator) { if (isEmpty(string)) { return string; } if (separator == null) { return ""; } final int pos = string.indexOf(separator); if (pos == -1) { return ""; } return string.substring(pos + separator.length()); } public static int nextRandomInt() { return (int)(Math.random() * Integer.MAX_VALUE); } public static byte[] appendArrays(final byte[] firstArray, final byte[] secondArray) { validateNotNull(firstArray, "Appended array cannot be null"); validateNotNull(secondArray, "Appended array cannot be null"); final byte[] result = new byte[firstArray.length + secondArray.length]; System.arraycopy(firstArray, 0, result, 0, firstArray.length); System.arraycopy(secondArray, 0, result, firstArray.length, secondArray.length); return result; } // This class should only be called statically private CommonUtils() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/000077500000000000000000000000001360667575700241035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/000077500000000000000000000000001360667575700246725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/000077500000000000000000000000001360667575700261135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/000077500000000000000000000000001360667575700275665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/000077500000000000000000000000001360667575700313055ustar00rootroot00000000000000BinaryDecoder.java000066400000000000000000000032121360667575700346010ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** * Defines common decoding methods for byte array decoders. * * @author Apache Software Foundation */ public interface BinaryDecoder extends Decoder { /** * Decodes a byte array and returns the results as a byte array. * * @param pArray A byte array which has been encoded with the * appropriate encoder * * @return a byte array that contains decoded content * * @throws DecoderException A decoder exception is thrown * if a Decoder encounters a failure condition during * the decode process. */ byte[] decode(byte[] pArray) throws DecoderException; } BinaryEncoder.java000066400000000000000000000031021360667575700346110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** * Defines common encoding methods for byte array encoders. * * @author Apache Software Foundation */ public interface BinaryEncoder extends Encoder { /** * Encodes a byte array and return the encoded data * as a byte array. * * @param pArray Data to be encoded * * @return A byte array containing the encoded data * * @throws EncoderException thrown if the Encoder * encounters a failure condition during the * encoding process. */ byte[] encode(byte[] pArray) throws EncoderException; } Decoder.java000066400000000000000000000043351360667575700334430ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** *

Provides the highest level of abstraction for Decoders. * This is the sister interface of {@link Encoder}. All * Decoders implement this common generic interface.

* *

Allows a user to pass a generic Object to any Decoder * implementation in the codec package.

* *

One of the two interfaces at the center of the codec package.

* * @author Apache Software Foundation */ public interface Decoder { /** * Decodes an "encoded" Object and returns a "decoded" * Object. Note that the implementation of this * interface will try to cast the Object parameter * to the specific type expected by a particular Decoder * implementation. If a {@link java.lang.ClassCastException} occurs * this decode method will throw a DecoderException. * * @param pObject an object to "decode" * * @return a 'decoded" object * * @throws DecoderException a decoder exception can * be thrown for any number of reasons. Some good * candidates are that the parameter passed to this * method is null, a param cannot be cast to the * appropriate type for a specific encoder. */ Object decode(Object pObject) throws DecoderException; } DecoderException.java000066400000000000000000000025711360667575700353220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** * Thrown when a Decoder has encountered a failure condition during a decode. * * @author Apache Software Foundation */ public class DecoderException extends Exception { /** * Creates a DecoderException * * @param pMessage A message with meaning to a human */ public DecoderException(String pMessage) { super(pMessage); } } Encoder.java000066400000000000000000000036161360667575700334560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** *

Provides the highest level of abstraction for Encoders. * This is the sister interface of {@link Decoder}. Every implementation of * Encoder provides this common generic interface whic allows a user to pass a * generic Object to any Encoder implementation in the codec package.

* * @author Apache Software Foundation */ public interface Encoder { /** * Encodes an "Object" and returns the encoded content * as an Object. The Objects here may just be byte[] * or Strings depending on the implementation used. * * @param pObject An object ot encode * * @return An "encoded" Object * * @throws EncoderException an encoder exception is * thrown if the encoder experiences a failure * condition during the encoding process. */ Object encode(Object pObject) throws EncoderException; } EncoderException.java000066400000000000000000000031571360667575700353350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3; /** * Thrown when there is a failure condition during the encoding process. This * exception is thrown when an Encoder encounters a encoding specific exception * such as invalid data, inability to calculate a checksum, characters outside of the * expected range. * * @author Apache Software Foundation */ public class EncoderException extends Exception { /** * Creates a new instance of this exception with an useful message. * * @param pMessage a useful message relating to the encoder specific error. */ public EncoderException(String pMessage) { super(pMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/binary/000077500000000000000000000000001360667575700325715ustar00rootroot00000000000000Base64.java000066400000000000000000000434071360667575700344110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/contrib/org/apache/commons/codec_1_3/binary/* * Copyright 2001-2004 The Apache Software Foundation. * * 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. */ /* * IMPORTANT NOTE: This class has been included into Jasypt's source tree from * Apache Commons-Codec version 1.3 [see http://commons.apache.org/codec], * licensed under Apache License 2.0 [see http://www.apache.org/licenses/LICENSE-2.0]. * No modifications have been made to the code of this class except the package name. */ package org.jasypt.contrib.org.apache.commons.codec_1_3.binary; import org.jasypt.contrib.org.apache.commons.codec_1_3.BinaryDecoder; import org.jasypt.contrib.org.apache.commons.codec_1_3.BinaryEncoder; import org.jasypt.contrib.org.apache.commons.codec_1_3.DecoderException; import org.jasypt.contrib.org.apache.commons.codec_1_3.EncoderException; /** * Provides Base64 encoding and decoding as defined by RFC 2045. * *

This class implements section 6.8. Base64 Content-Transfer-Encoding * from RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies by Freed and Borenstein.

* * @see RFC 2045 * @author Apache Software Foundation * @since 1.0-dev */ public class Base64 implements BinaryEncoder, BinaryDecoder { /** * Chunk size per RFC 2045 section 6.8. * *

The {@value} character limit does not count the trailing CRLF, but counts * all other characters, including any equal signs.

* * @see RFC 2045 section 6.8 */ static final int CHUNK_SIZE = 76; /** * Chunk separator per RFC 2045 section 2.1. * * @see RFC 2045 section 2.1 */ static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes(); /** * The base length. */ static final int BASELENGTH = 255; /** * Lookup length. */ static final int LOOKUPLENGTH = 64; /** * Used to calculate the number of bits in a byte. */ static final int EIGHTBIT = 8; /** * Used when encoding something which has fewer than 24 bits. */ static final int SIXTEENBIT = 16; /** * Used to determine how many bits data contains. */ static final int TWENTYFOURBITGROUP = 24; /** * Used to get the number of Quadruples. */ static final int FOURBYTE = 4; /** * Used to test the sign of a byte. */ static final int SIGN = -128; /** * Byte used to pad output. */ static final byte PAD = (byte) '='; // Create arrays to hold the base64 characters and a // lookup for base64 chars private static byte[] base64Alphabet = new byte[BASELENGTH]; private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; // Populating the lookup and character arrays static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = (byte) -1; } for (int i = 'Z'; i >= 'A'; i--) { base64Alphabet[i] = (byte) (i - 'A'); } for (int i = 'z'; i >= 'a'; i--) { base64Alphabet[i] = (byte) (i - 'a' + 26); } for (int i = '9'; i >= '0'; i--) { base64Alphabet[i] = (byte) (i - '0' + 52); } base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; for (int i = 0; i <= 25; i++) { lookUpBase64Alphabet[i] = (byte) ('A' + i); } for (int i = 26, j = 0; i <= 51; i++, j++) { lookUpBase64Alphabet[i] = (byte) ('a' + j); } for (int i = 52, j = 0; i <= 61; i++, j++) { lookUpBase64Alphabet[i] = (byte) ('0' + j); } lookUpBase64Alphabet[62] = (byte) '+'; lookUpBase64Alphabet[63] = (byte) '/'; } private static boolean isBase64(byte octect) { if (octect == PAD) { return true; } else if (base64Alphabet[octect] == -1) { return false; } else { return true; } } /** * Tests a given byte array to see if it contains * only valid characters within the Base64 alphabet. * * @param arrayOctect byte array to test * @return true if all bytes are valid characters in the Base64 * alphabet or if the byte array is empty; false, otherwise */ public static boolean isArrayByteBase64(byte[] arrayOctect) { arrayOctect = discardWhitespace(arrayOctect); int length = arrayOctect.length; if (length == 0) { // shouldn't a 0 length array be valid base64 data? // return false; return true; } for (int i = 0; i < length; i++) { if (!isBase64(arrayOctect[i])) { return false; } } return true; } /** * Encodes binary data using the base64 algorithm but * does not chunk the output. * * @param binaryData binary data to encode * @return Base64 characters */ public static byte[] encodeBase64(byte[] binaryData) { return encodeBase64(binaryData, false); } /** * Encodes binary data using the base64 algorithm and chunks * the encoded output into 76 character blocks * * @param binaryData binary data to encode * @return Base64 characters chunked in 76 character blocks */ public static byte[] encodeBase64Chunked(byte[] binaryData) { return encodeBase64(binaryData, true); } /** * Decodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Decoder interface, and will throw a DecoderException if the * supplied object is not of type byte[]. * * @param pObject Object to decode * @return An object (of type byte[]) containing the * binary data which corresponds to the byte[] supplied. * @throws DecoderException if the parameter supplied is not * of type byte[] */ public Object decode(Object pObject) throws DecoderException { if (!(pObject instanceof byte[])) { throw new DecoderException("Parameter supplied to Base64 decode is not a byte[]"); } return decode((byte[]) pObject); } /** * Decodes a byte[] containing containing * characters in the Base64 alphabet. * * @param pArray A byte array containing Base64 character data * @return a byte array containing binary data */ public byte[] decode(byte[] pArray) { return decodeBase64(pArray); } /** * Encodes binary data using the base64 algorithm, optionally * chunking the output into 76 character blocks. * * @param binaryData Array containing binary data to encode. * @param isChunked if isChunked is true this encoder will chunk * the base64 output into 76 character blocks * @return Base64-encoded data. */ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) { int lengthDataBits = binaryData.length * EIGHTBIT; int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; byte encodedData[] = null; int encodedDataLength = 0; int nbrChunks = 0; if (fewerThan24bits != 0) { //data not divisible by 24 bit encodedDataLength = (numberTriplets + 1) * 4; } else { // 16 or 8 bit encodedDataLength = numberTriplets * 4; } // If the output is to be "chunked" into 76 character sections, // for compliance with RFC 2045 MIME, then it is important to // allow for extra length to account for the separator(s) if (isChunked) { nbrChunks = (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE)); encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length; } encodedData = new byte[encodedDataLength]; byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; int nextSeparatorIndex = CHUNK_SIZE; int chunksSoFar = 0; //log.debug("number of triplets = " + numberTriplets); for (i = 0; i < numberTriplets; i++) { dataIndex = i * 3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3); l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; //log.debug( "val2 = " + val2 ); //log.debug( "k4 = " + (k<<4) ); //log.debug( "vak = " + (val2 | (k<<4)) ); encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[(l << 2) | val3]; encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f]; encodedIndex += 4; // If we are chunking, let's put a chunk separator down. if (isChunked) { // this assumes that CHUNK_SIZE % 4 == 0 if (encodedIndex == nextSeparatorIndex) { System.arraycopy( CHUNK_SEPARATOR, 0, encodedData, encodedIndex, CHUNK_SEPARATOR.length); chunksSoFar++; nextSeparatorIndex = (CHUNK_SIZE * (chunksSoFar + 1)) + (chunksSoFar * CHUNK_SEPARATOR.length); encodedIndex += CHUNK_SEPARATOR.length; } } } // form integral number of 6-bit groups dataIndex = i * 3; if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) (b1 & 0x03); //log.debug("b1=" + b1); //log.debug("b1<<2 = " + (b1>>2) ); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex + 3] = PAD; } if (isChunked) { // we also add a separator to the end of the final chunk. if (chunksSoFar < nbrChunks) { System.arraycopy( CHUNK_SEPARATOR, 0, encodedData, encodedDataLength - CHUNK_SEPARATOR.length, CHUNK_SEPARATOR.length); } } return encodedData; } /** * Decodes Base64 data into octects * * @param base64Data Byte array containing Base64 data * @return Array containing decoded data. */ public static byte[] decodeBase64(byte[] base64Data) { // RFC 2045 requires that we discard ALL non-Base64 characters base64Data = discardNonBase64(base64Data); // handle the edge case, so we don't have to worry about it later if (base64Data.length == 0) { return new byte[0]; } int numberQuadruple = base64Data.length / FOURBYTE; byte decodedData[] = null; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; // Throw away anything not in base64Data int encodedIndex = 0; int dataIndex = 0; { // this sizes the output array properly - rlw int lastData = base64Data.length; // ignore the '=' padding while (base64Data[lastData - 1] == PAD) { if (--lastData == 0) { return new byte[0]; } } decodedData = new byte[lastData - numberQuadruple]; } for (int i = 0; i < numberQuadruple; i++) { dataIndex = i * 4; marker0 = base64Data[dataIndex + 2]; marker1 = base64Data[dataIndex + 3]; b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex + 1]]; if (marker0 != PAD && marker1 != PAD) { //No PAD e.g 3cQl b3 = base64Alphabet[marker0]; b4 = base64Alphabet[marker1]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); } else if (marker0 == PAD) { //Two PAD e.g. 3c[Pad][Pad] decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); } else if (marker1 == PAD) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[marker0]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); } encodedIndex += 3; } return decodedData; } /** * Discards any whitespace from a base-64 encoded block. * * @param data The base-64 encoded data to discard the whitespace * from. * @return The data, less whitespace (see RFC 2045). */ static byte[] discardWhitespace(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { switch (data[i]) { case (byte) ' ' : case (byte) '\n' : case (byte) '\r' : case (byte) '\t' : break; default: groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } /** * Discards any characters outside of the base64 alphabet, per * the requirements on page 25 of RFC 2045 - "Any characters * outside of the base64 alphabet are to be ignored in base64 * encoded data." * * @param data The base-64 encoded data to groom * @return The data, less non-base64 characters (see RFC 2045). */ static byte[] discardNonBase64(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { if (isBase64(data[i])) { groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } // Implementation of the Encoder Interface /** * Encodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Encoder interface, and will throw an EncoderException if the * supplied object is not of type byte[]. * * @param pObject Object to encode * @return An object (of type byte[]) containing the * base64 encoded data which corresponds to the byte[] supplied. * @throws EncoderException if the parameter supplied is not * of type byte[] */ public Object encode(Object pObject) throws EncoderException { if (!(pObject instanceof byte[])) { throw new EncoderException( "Parameter supplied to Base64 encode is not a byte[]"); } return encode((byte[]) pObject); } /** * Encodes a byte[] containing binary data, into a byte[] containing * characters in the Base64 alphabet. * * @param pArray a byte array containing binary data * @return A byte array containing only Base64 character data */ public byte[] encode(byte[] pArray) { return encodeBase64(pArray, false); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/000077500000000000000000000000001360667575700237225ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/ByteDigester.java000066400000000000000000000033521360667575700271620ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; /** *

* Common interface for all digesters which receive a byte array message and * return a byte array digest. *

*

* For a default implementation, see {@link StandardByteDigester}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface ByteDigester { /** *

* Create a digest of the input message. *

* * @param message the message to be digested * @return the digest */ public byte[] digest(byte[] message); /** *

* Check whether a message matches a digest, managing aspects like * salt, hashing iterations, etc. (if applicable). *

* * @param message the message to check * @param digest the digest to check * @return TRUE if the message matches the digest, FALSE if not. */ public boolean matches(byte[] message, byte[] digest); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/PooledByteDigester.java000066400000000000000000000512561360667575700303330ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link ByteDigester} that in fact contains * an array of {@link StandardByteDigester} objects which are used * to attend digest and match requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardByteDigester}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public class PooledByteDigester implements ByteDigester { private final StandardByteDigester firstDigester; private DigesterConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardByteDigester[] pool; private int roundRobin = 0; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardByteDigester. */ public PooledByteDigester() { super(); this.firstDigester = new StandardByteDigester(); } /** *

* Sets a {@link org.jasypt.digest.config.DigesterConfig} object * for the digester. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Salt size
  • *
  • Hashing iterations
  • *
  • Salt generator
  • *
  • Location of the salt in relation to the encrypted message * (default: before)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the DigesterConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final DigesterConfig config) { this.firstDigester.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(final String algorithm) { this.firstDigester.setAlgorithm(algorithm); } /** *

* Sets the size of the salt to be used to compute the digest. * This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* *

* If salt size is set to zero, then no salt will be used. *

* * @param saltSizeBytes the size of the salt to be used, in bytes. */ public synchronized void setSaltSizeBytes(final int saltSizeBytes) { this.firstDigester.setSaltSizeBytes(saltSizeBytes); } /** *

* Set the number of times the hash function will be applied recursively. *
* The hash function will be applied to its own results as many times as * specified: h(h(...h(x)...)) *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param iterations the number of iterations. */ public synchronized void setIterations(final int iterations) { this.firstDigester.setIterations(iterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(final SaltGenerator saltGenerator) { this.firstDigester.setSaltGenerator(saltGenerator); } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the digest algorithm. */ public synchronized void setProviderName(final String providerName) { this.firstDigester.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(final Provider provider) { this.firstDigester.setProvider(provider); } /** *

* Whether the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of salt before message) will be applied. *

* * @param invertPositionOfSaltInMessageBeforeDigesting * whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). */ public synchronized void setInvertPositionOfSaltInMessageBeforeDigesting( final boolean invertPositionOfSaltInMessageBeforeDigesting) { this.firstDigester.setInvertPositionOfSaltInMessageBeforeDigesting(invertPositionOfSaltInMessageBeforeDigesting); } /** *

* Whether the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of plain salt before digest result) will be applied. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResults * whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). */ public synchronized void setInvertPositionOfPlainSaltInEncryptionResults( final boolean invertPositionOfPlainSaltInEncryptionResults) { this.firstDigester.setInvertPositionOfPlainSaltInEncryptionResults(invertPositionOfPlainSaltInEncryptionResults); } /** *

* Whether digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* If this parameter is not explicitly set, the default behaviour * (NOT lenient) will be applied. *

* * @param useLenientSaltSizeCheck whether the digester will allow matching of * digests with different salt sizes than established or not (default * is false). */ public synchronized void setUseLenientSaltSizeCheck(final boolean useLenientSaltSizeCheck) { this.firstDigester.setUseLenientSaltSizeCheck(useLenientSaltSizeCheck); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the digester has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
*

* Once a digester has been initialized, trying to * change its configuration (algorithm, provider, salt size, iterations * or salt generator) will * result in an AlreadyInitializedException being thrown. *

* * @return true if the digester has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the digester. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the digester with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a * {@link org.jasypt.digest.config.DigesterConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* Once a digester has been initialized, trying to * change its configuration will result in an * AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = new StandardByteDigester[this.poolSize]; this.pool[0] = this.firstDigester; for (int i = 1; i < this.poolSize; i++) { this.pool[i] = this.pool[i - 1].cloneDigester(); } this.initialized = true; } } /** *

* Performs a digest operation on a byte array message. *

*

* The steps taken for creating the digest are: *

    *
  1. A salt of the specified size is generated (see * {@link SaltGenerator}).
  2. *
  3. The salt bytes are added to the message.
  4. *
  5. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  6. *
  7. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  8. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
*

*

* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed * with the same salt on a different message to check if both messages * match (all of which will be managed automatically by the * matches method). *

* * @param message the byte array to be digested * @return the digest result * @throws EncryptionOperationNotPossibleException if the digest operation * fails, ommitting any further information about the cause for * security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public byte[] digest(byte[] message) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].digest(message); } /** *

* Checks a message against a given digest. *

*

* This method tells whether a message corresponds to a specific digest * or not by getting the salt with which the digest was created and * applying it to a digest operation performed on the message. If * new and existing digest match, the message is said to match the digest. *

*

* This method will be used, for instance, for password checking in * authentication processes. *

*

* A null message will only match a null digest. *

* * @param message the message to be compared to the digest. * @param digest the digest. * @return true if the specified message matches the digest, false * if not. * @throws EncryptionOperationNotPossibleException if the digest matching * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public boolean matches(final byte[] message, final byte[] digest) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].matches(message, digest); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/PooledStringDigester.java000066400000000000000000000577351360667575700307060ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link StringDigester} that in fact contains * an array of {@link StandardStringDigester} objects which are used * to attend digest and match requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardStringDigester}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public class PooledStringDigester implements StringDigester { private final StandardStringDigester firstDigester; private DigesterConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardStringDigester[] pool; private int roundRobin = 0; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardStringDigester. */ public PooledStringDigester() { super(); this.firstDigester = new StandardStringDigester(); } /** *

* Sets a {@link org.jasypt.digest.config.DigesterConfig} * or {@link StringDigesterConfig} object * for the digester. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Salt size
  • *
  • Hashing iterations
  • *
  • Salt generator
  • *
  • Use of Unicode normalization mechanisms * (only StringDigesterConfig)
  • *
  • Output type (base64, hexadecimal) * (only StringDigesterConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the DigesterConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final DigesterConfig config) { this.firstDigester.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(final String algorithm) { this.firstDigester.setAlgorithm(algorithm); } /** *

* Sets the size of the salt to be used to compute the digest. * This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* *

* If salt size is set to zero, then no salt will be used. *

* * @param saltSizeBytes the size of the salt to be used, in bytes. */ public synchronized void setSaltSizeBytes(final int saltSizeBytes) { this.firstDigester.setSaltSizeBytes(saltSizeBytes); } /** *

* Set the number of times the hash function will be applied recursively. *
* The hash function will be applied to its own results as many times as * specified: h(h(...h(x)...)) *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param iterations the number of iterations. */ public synchronized void setIterations(final int iterations) { this.firstDigester.setIterations(iterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(final SaltGenerator saltGenerator) { this.firstDigester.setSaltGenerator(saltGenerator); } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the digest algorithm. */ public synchronized void setProviderName(final String providerName) { this.firstDigester.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(final Provider provider) { this.firstDigester.setProvider(provider); } /** *

* Whether the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of salt before message) will be applied. *

* * @param invertPositionOfSaltInMessageBeforeDigesting * whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). */ public synchronized void setInvertPositionOfSaltInMessageBeforeDigesting( final boolean invertPositionOfSaltInMessageBeforeDigesting) { this.firstDigester.setInvertPositionOfSaltInMessageBeforeDigesting(invertPositionOfSaltInMessageBeforeDigesting); } /** *

* Whether the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of plain salt before digest result) will be applied. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResults * whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). */ public synchronized void setInvertPositionOfPlainSaltInEncryptionResults( final boolean invertPositionOfPlainSaltInEncryptionResults) { this.firstDigester.setInvertPositionOfPlainSaltInEncryptionResults(invertPositionOfPlainSaltInEncryptionResults); } /** *

* Whether digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* If this parameter is not explicitly set, the default behaviour * (NOT lenient) will be applied. *

* * @param useLenientSaltSizeCheck whether the digester will allow matching of * digests with different salt sizes than established or not (default * is false). */ public synchronized void setUseLenientSaltSizeCheck(final boolean useLenientSaltSizeCheck) { this.firstDigester.setUseLenientSaltSizeCheck(useLenientSaltSizeCheck); } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

* * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public synchronized void setUnicodeNormalizationIgnored(final boolean unicodeNormalizationIgnored) { this.firstDigester.setUnicodeNormalizationIgnored(unicodeNormalizationIgnored); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @param stringOutputType the string output type. */ public synchronized void setStringOutputType(final String stringOutputType) { this.firstDigester.setStringOutputType(stringOutputType); } /** *

* Sets the prefix to be added at the beginning of encryption results, and also to * be expected at the beginning of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* By default, no prefix will be added to encryption results. *

* * @param prefix the prefix to be set */ public synchronized void setPrefix(final String prefix) { this.firstDigester.setPrefix(prefix); } /** *

* Sets the suffix to be added at the end of encryption results, and also to * be expected at the end of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* By default, no suffix will be added to encryption results. *

* * @param suffix the suffix to be set */ public synchronized void setSuffix(final String suffix) { this.firstDigester.setSuffix(suffix); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the digester has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
*

* Once a digester has been initialized, trying to * change its configuration (algorithm, provider, salt size, iterations * or salt generator) will * result in an AlreadyInitializedException being thrown. *

* * @return true if the digester has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the digester. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the digester with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a * {@link org.jasypt.digest.config.DigesterConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* Once a digester has been initialized, trying to * change its configuration will result in an * AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = new StandardStringDigester[this.poolSize]; this.pool[0] = this.firstDigester; for (int i = 1; i < this.poolSize; i++) { this.pool[i] = this.pool[i - 1].cloneDigester(); } this.initialized = true; } } /** *

* Performs a digest operation on a String message. *

*

* The steps taken for creating the digest are: *

    *
  1. The String message is converted to a byte array.
  2. *
  3. A salt of the specified size is generated (see * {@link org.jasypt.salt.SaltGenerator}).
  4. *
  5. The salt bytes are added to the message.
  6. *
  7. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  8. *
  9. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  10. *
  11. The result of the concatenation is encoded in BASE64 (default) * or HEXADECIMAL * and returned as an ASCII String.
  12. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
*

*

* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed * with the same salt on a different message to check if both messages * match (all of which will be managed automatically by the * matches method). *

* * @param message the String to be digested * @return the digest result * @throws EncryptionOperationNotPossibleException if the digest operation * fails, ommitting any further information about the cause for * security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public String digest(final String message) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].digest(message); } /** *

* Checks a message against a given digest. *

*

* This method tells whether a message corresponds to a specific digest * or not by getting the salt with which the digest was created and * applying it to a digest operation performed on the message. If * new and existing digest match, the message is said to match the digest. *

*

* This method will be used, for instance, for password checking in * authentication processes. *

*

* A null message will only match a null digest. *

* * @param message the message to be compared to the digest. * @param digest the digest. * @return true if the specified message matches the digest, false * if not. * @throws EncryptionOperationNotPossibleException if the digest matching * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public boolean matches(final String message, final String digest) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].matches(message, digest); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/StandardByteDigester.java000066400000000000000000001266061360667575700306530ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.salt.RandomSaltGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link ByteDigester} interface. * This class lets the user specify the algorithm (and provider) to be used for * creating digests, the size of the salt to be applied, * the number of times the hash function will be applied (iterations) and * the salt generator to be used. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, salt size iterations and salt generator * can take values in any of these ways: *

    *
  • Using its default values.
  • *
  • Setting a {@link org.jasypt.digest.config.DigesterConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setAlgorithm(...), setProvider(...), * setProviderName(...), * setSaltSizeBytes(...), setIterations(...) * or setSaltGenerator(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a {@link org.jasypt.digest.config.DigesterConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to create digests, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
* Once a digester has been initialized, trying to * change its configuration (algorithm, provider, salt size, iterations or * salt generator) * will result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* A digester may be used in two different ways: *

    *
  • For creating digests, by calling the digest method.
  • *
  • For matching digests, this is, checking whether a digest * corresponds adequately to a digest (as in password checking) or not, by * calling the matches method.
  • *
* The steps taken for creating digests are: *
    *
  1. A salt of the specified size is generated (see * {@link SaltGenerator}). If salt size is zero, no salt will be * used.
  2. *
  3. The salt bytes are added to the message.
  4. *
  5. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  6. *
  7. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  8. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed with * the same salt on a different message to check if both messages match * (all of which will be managed automatically by the matches method). *

*

* To learn more about the mechanisms involved in digest creation, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.0 * * @author Daniel Fernández * */ public final class StandardByteDigester implements ByteDigester { /** * Default digest algorithm will be MD5 */ public static final String DEFAULT_ALGORITHM = "MD5"; /** * The minimum recommended size for salt is 8 bytes */ public static final int DEFAULT_SALT_SIZE_BYTES = 8; /** * The minimum recommended iterations for hashing are 1000 */ public static final int DEFAULT_ITERATIONS = 1000; // Algorithm to be used for hashing private String algorithm = DEFAULT_ALGORITHM; // Size of salt to be applied private int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES; // Number of hash iterations to be applied private int iterations = DEFAULT_ITERATIONS; // SaltGenerator to be used. Initialization of a salt generator is costly, // and so default value will be applied only in initialize(), if it finally // becomes necessary. private SaltGenerator saltGenerator = null; // Name of the java.security.Provider which will be asked for the selected // algorithm private String providerName = null; // java.security.Provider instance which will be asked for the selected // algorithm private Provider provider = null; // Whether salt bytes will be appended after message before digesting or // inserted before it (which is the default). private boolean invertPositionOfSaltInMessageBeforeDigesting = false; // Whether plain (unhashed) salt bytes will be appended after the digest // operation result or inserted before it (which is the default). private boolean invertPositionOfPlainSaltInEncryptionResults = false; // Whether digest matching operations will allow matching digests with a // salt size different to the one configured in the "saltSizeBytes" property. private boolean useLenientSaltSizeCheck = false; /* * Config: this object can set a configuration by bringing the values in * whichever way the developer wants (it only has to implement the * DigesterConfig interface). * * Calls to setX methods OVERRIDE the values brought by this config. */ private DigesterConfig config = null; /* * Set of booleans which indicate whether the config or default values * have to be overriden because of the setX methods having been * called. */ private boolean algorithmSet = false; private boolean saltSizeBytesSet = false; private boolean iterationsSet = false; private boolean saltGeneratorSet = false; private boolean providerNameSet = false; private boolean providerSet = false; private boolean invertPositionOfSaltInMessageBeforeDigestingSet = false; private boolean invertPositionOfPlainSaltInEncryptionResultsSet = false; private boolean useLenientSaltSizeCheckSet = false; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /* * If the salt size is set to a value higher than zero, this flag will * indicate that the salt mecanism has to be used. */ private boolean useSalt = true; /* * MessageDigest to be used. * * IMPORTANT: MessageDigest is not a thread-safe class, and thus any * use of this variable will have to be adequately synchronized. */ private MessageDigest md = null; /* * Length of the result digest for the specified algorithm. * This might be zero if this operation is not supported by the * algorithm provider and the implementation is not cloneable. */ private int digestLengthBytes = 0; /** * Creates a new instance of StandardByteDigester. */ public StandardByteDigester() { super(); } /** *

* Sets a {@link org.jasypt.digest.config.DigesterConfig} object * for the digester. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Salt size
  • *
  • Hashing iterations
  • *
  • Salt generator
  • *
  • Location of the salt in relation to the encrypted message * (default: before)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the DigesterConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final DigesterConfig config) { CommonUtils.validateNotNull(config, "Config cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.config = config; } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(final String algorithm) { CommonUtils.validateNotEmpty(algorithm, "Algorithm cannot be empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.algorithm = algorithm; this.algorithmSet = true; } /** *

* Sets the size of the salt to be used to compute the digest. * This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* *

* If salt size is set to zero, then no salt will be used. *

* * @param saltSizeBytes the size of the salt to be used, in bytes. */ public synchronized void setSaltSizeBytes(final int saltSizeBytes) { CommonUtils.validateIsTrue(saltSizeBytes >= 0, "Salt size in bytes must be non-negative"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.saltSizeBytes = saltSizeBytes; this.useSalt = (saltSizeBytes > 0); this.saltSizeBytesSet = true; } /** *

* Set the number of times the hash function will be applied recursively. *
* The hash function will be applied to its own results as many times as * specified: h(h(...h(x)...)) *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param iterations the number of iterations. */ public synchronized void setIterations(final int iterations) { CommonUtils.validateIsTrue(iterations > 0, "Number of iterations must be greater than zero"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.iterations = iterations; this.iterationsSet = true; } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @since 1.2 * * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(final SaltGenerator saltGenerator) { CommonUtils.validateNotNull(saltGenerator, "Salt generator cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the digest algorithm. */ public synchronized void setProviderName(final String providerName) { CommonUtils.validateNotNull(providerName, "Provider name cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.providerName = providerName; this.providerNameSet = true; } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(final Provider provider) { CommonUtils.validateNotNull(provider, "Provider cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.provider = provider; this.providerSet = true; } /** *

* Whether the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of salt before message) will be applied. *

* * @since 1.7 * * @param invertPositionOfSaltInMessageBeforeDigesting * whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). */ public synchronized void setInvertPositionOfSaltInMessageBeforeDigesting( final boolean invertPositionOfSaltInMessageBeforeDigesting) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.invertPositionOfSaltInMessageBeforeDigesting = invertPositionOfSaltInMessageBeforeDigesting; this.invertPositionOfSaltInMessageBeforeDigestingSet = true; } /** *

* Whether the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of plain salt before digest result) will be applied. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResults * whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). */ public synchronized void setInvertPositionOfPlainSaltInEncryptionResults( final boolean invertPositionOfPlainSaltInEncryptionResults) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.invertPositionOfPlainSaltInEncryptionResults = invertPositionOfPlainSaltInEncryptionResults; this.invertPositionOfPlainSaltInEncryptionResultsSet = true; } /** *

* Whether digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* If this parameter is not explicitly set, the default behaviour * (NOT lenient) will be applied. *

* * @since 1.7 * * @param useLenientSaltSizeCheck whether the digester will allow matching of * digests with different salt sizes than established or not (default * is false). */ public synchronized void setUseLenientSaltSizeCheck(final boolean useLenientSaltSizeCheck) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.useLenientSaltSizeCheck = useLenientSaltSizeCheck; this.useLenientSaltSizeCheckSet = true; } /* * Clone this digester. */ StandardByteDigester cloneDigester() { // Check initialization if (!isInitialized()) { initialize(); } final StandardByteDigester cloned = new StandardByteDigester(); if (CommonUtils.isNotEmpty(this.algorithm)) { cloned.setAlgorithm(this.algorithm); } cloned.setInvertPositionOfPlainSaltInEncryptionResults(this.invertPositionOfPlainSaltInEncryptionResults); cloned.setInvertPositionOfSaltInMessageBeforeDigesting(this.invertPositionOfSaltInMessageBeforeDigesting); cloned.setIterations(this.iterations); if (this.provider != null) { cloned.setProvider(this.provider); } if (this.providerName != null) { cloned.setProviderName(this.providerName); } if (this.saltGenerator != null) { cloned.setSaltGenerator(this.saltGenerator); } cloned.setSaltSizeBytes(this.saltSizeBytes); cloned.setUseLenientSaltSizeCheck(this.useLenientSaltSizeCheck); return cloned; } /** *

* Returns true if the digester has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
*

* Once a digester has been initialized, trying to * change its configuration (algorithm, provider, salt size, iterations * or salt generator) will * result in an AlreadyInitializedException being thrown. *

* * @return true if the digester has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the digester. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the digester with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a * {@link org.jasypt.digest.config.DigesterConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* Once a digester has been initialized, trying to * change its configuration will result in an * AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { /* * If a DigesterConfig object has been set, we need to * consider the values it returns (if, for each value, the * corresponding "setX" method has not been called). */ if (this.config != null) { final String configAlgorithm = this.config.getAlgorithm(); if (configAlgorithm != null) { CommonUtils.validateNotEmpty(configAlgorithm, "Algorithm cannot be empty"); } final Integer configSaltSizeBytes = this.config.getSaltSizeBytes(); if (configSaltSizeBytes != null) { CommonUtils.validateIsTrue(configSaltSizeBytes.intValue() >= 0, "Salt size in bytes must be non-negative"); } final Integer configIterations = this.config.getIterations(); if (configIterations != null) { CommonUtils.validateIsTrue(configIterations.intValue() > 0, "Number of iterations must be greater than zero"); } final SaltGenerator configSaltGenerator = this.config.getSaltGenerator(); final String configProviderName = this.config.getProviderName(); if (configProviderName != null) { CommonUtils.validateNotEmpty(configProviderName, "Provider name cannot be empty"); } final Provider configProvider = this.config.getProvider(); final Boolean configInvertPositionOfSaltInMessageBeforeDigesting = this.config.getInvertPositionOfSaltInMessageBeforeDigesting(); final Boolean configInvertPositionOfPlainSaltInEncryptionResults = this.config.getInvertPositionOfPlainSaltInEncryptionResults(); final Boolean configUseLenientSaltSizeCheck = this.config.getUseLenientSaltSizeCheck(); this.algorithm = ((this.algorithmSet) || (configAlgorithm == null))? this.algorithm : configAlgorithm; this.saltSizeBytes = ((this.saltSizeBytesSet) || (configSaltSizeBytes == null))? this.saltSizeBytes : configSaltSizeBytes.intValue(); this.iterations = ((this.iterationsSet) || (configIterations == null))? this.iterations : configIterations.intValue(); this.saltGenerator = ((this.saltGeneratorSet) || (configSaltGenerator == null))? this.saltGenerator : configSaltGenerator; this.providerName = ((this.providerNameSet) || (configProviderName == null))? this.providerName : configProviderName; this.provider = ((this.providerSet) || (configProvider == null))? this.provider : configProvider; this.invertPositionOfSaltInMessageBeforeDigesting = ((this.invertPositionOfSaltInMessageBeforeDigestingSet) || (configInvertPositionOfSaltInMessageBeforeDigesting == null))? this.invertPositionOfSaltInMessageBeforeDigesting : configInvertPositionOfSaltInMessageBeforeDigesting.booleanValue(); this.invertPositionOfPlainSaltInEncryptionResults = ((this.invertPositionOfPlainSaltInEncryptionResultsSet) || (configInvertPositionOfPlainSaltInEncryptionResults == null))? this.invertPositionOfPlainSaltInEncryptionResults : configInvertPositionOfPlainSaltInEncryptionResults.booleanValue(); this.useLenientSaltSizeCheck = ((this.useLenientSaltSizeCheckSet) || (configUseLenientSaltSizeCheck == null))? this.useLenientSaltSizeCheck : configUseLenientSaltSizeCheck.booleanValue(); } /* * If the digester was not set a salt generator in any way, * it is time to apply its default value. */ if (this.saltGenerator == null) { this.saltGenerator = new RandomSaltGenerator(); } /* * Test compatibility of salt generator with salt size checking * behaviour */ if (this.useLenientSaltSizeCheck) { if (!this.saltGenerator.includePlainSaltInEncryptionResults()) { throw new EncryptionInitializationException( "The configured Salt Generator (" + this.saltGenerator.getClass().getName() + ") does not include plain salt " + "in encryption results, which is not compatible" + "with setting the salt size checking behaviour to \"lenient\"."); } } /* * MessageDigest is initialized the usual way, and the digester * is marked as "initialized" so that configuration cannot be * changed in the future. */ try { if (this.provider != null) { this.md = MessageDigest.getInstance( this.algorithm, this.provider); } else if (this.providerName != null) { this.md = MessageDigest.getInstance( this.algorithm, this.providerName); } else { this.md = MessageDigest.getInstance(this.algorithm); } } catch (NoSuchAlgorithmException e) { throw new EncryptionInitializationException(e); } catch (NoSuchProviderException e) { throw new EncryptionInitializationException(e); } /* * Store the digest length (algorithm-dependent) and check * the operation is supported by the provider. */ this.digestLengthBytes = this.md.getDigestLength(); if (this.digestLengthBytes <= 0) { throw new EncryptionInitializationException( "The configured algorithm (" + this.algorithm + ") or its provider do " + "not allow knowing the digest length beforehand " + "(getDigestLength() operation), which is not compatible" + "with setting the salt size checking behaviour to \"lenient\"."); } this.initialized = true; } } /** *

* Performs a digest operation on a byte array message. *

*

* The steps taken for creating the digest are: *

    *
  1. A salt of the specified size is generated (see * {@link SaltGenerator}).
  2. *
  3. The salt bytes are added to the message.
  4. *
  5. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  6. *
  7. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  8. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
*

*

* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed * with the same salt on a different message to check if both messages * match (all of which will be managed automatically by the * matches method). *

* * @param message the byte array to be digested * @return the digest result * @throws EncryptionOperationNotPossibleException if the digest operation * fails, ommitting any further information about the cause for * security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public byte[] digest(byte[] message) { if (message == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } // Create salt byte[] salt = null; if (this.useSalt) { salt = this.saltGenerator.generateSalt(this.saltSizeBytes); } // Create digest return digest(message, salt); } /* * This method truly performs the digest operation, assuming that a salt * has already been created (if needed) and the digester has already been * initialized. */ private byte[] digest(final byte[] message, final byte[] salt) { try { byte[] digest = null; synchronized (this.md) { this.md.reset(); if (salt != null) { if (!this.invertPositionOfSaltInMessageBeforeDigesting) { // The salt bytes are added before the message to be digested this.md.update(salt); this.md.update(message); } else { // The salt bytes are appended after the message to be digested this.md.update(message); this.md.update(salt); } } else { //No salt to be added this.md.update(message); } digest = this.md.digest(); for (int i = 0; i < (this.iterations - 1); i++) { this.md.reset(); digest = this.md.digest(digest); } } // Finally we build an array containing both the unhashed (plain) salt // and the digest of the (salt + message). This is done only // if the salt generator we are using specifies to do so. if (this.saltGenerator.includePlainSaltInEncryptionResults() && salt != null) { if (!this.invertPositionOfPlainSaltInEncryptionResults) { // Insert unhashed salt before the hashing result (default behaviour) return CommonUtils.appendArrays(salt, digest); } // Append unhashed salt after the hashing result return CommonUtils.appendArrays(digest, salt); } return digest; } catch (Exception e) { // If digest fails, it is more secure not to return any information // about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Checks a message against a given digest. *

*

* This method tells whether a message corresponds to a specific digest * or not by getting the salt with which the digest was created and * applying it to a digest operation performed on the message. If * new and existing digest match, the message is said to match the digest. *

*

* This method will be used, for instance, for password checking in * authentication processes. *

*

* A null message will only match a null digest. *

* * @param message the message to be compared to the digest. * @param digest the digest. * @return true if the specified message matches the digest, false * if not. * @throws EncryptionOperationNotPossibleException if the digest matching * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public boolean matches(final byte[] message, final byte[] digest) { if (message == null) { return (digest == null); } else if (digest == null) { return false; } // Check initialization if (!isInitialized()) { initialize(); } try { // If we are using a salt, extract it to use it. byte[] salt = null; if (this.useSalt) { // If we are using a salt generator which specifies the salt // to be included into the digest itself, get it from there. // If not, the salt is supposed to be fixed and thus the // salt generator can be safely asked for it again. if (this.saltGenerator.includePlainSaltInEncryptionResults()) { // Compute size figures and perform length checks int digestSaltSize = this.saltSizeBytes; if (this.digestLengthBytes > 0) { if (this.useLenientSaltSizeCheck) { if (digest.length < this.digestLengthBytes) { throw new EncryptionOperationNotPossibleException(); } digestSaltSize = digest.length - this.digestLengthBytes; } else { if (digest.length != (this.digestLengthBytes + this.saltSizeBytes)) { throw new EncryptionOperationNotPossibleException(); } } } else { // Salt size check behaviour cannot be set to lenient if (digest.length < this.saltSizeBytes) { throw new EncryptionOperationNotPossibleException(); } } if (!this.invertPositionOfPlainSaltInEncryptionResults) { salt = new byte[digestSaltSize]; System.arraycopy(digest, 0, salt, 0, digestSaltSize); } else { salt = new byte[digestSaltSize]; System.arraycopy(digest, digest.length - digestSaltSize, salt, 0, digestSaltSize); } } else { salt = this.saltGenerator.generateSalt(this.saltSizeBytes); } } // Digest the message with the extracted digest. final byte[] encryptedMessage = digest(message, salt); // If, using the same salt, digests match, then messages too. return (digestsAreEqual(encryptedMessage, digest)); } catch (Exception e) { // If digest fails, it is more secure not to return any information // about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } // Time-constant comparison of byte arrays private static boolean digestsAreEqual(byte[] a, byte[] b) { if (a == null || b == null) { return false; } final int aLen = a.length; if (b.length != aLen) { return false; } int match = 0; for (int i = 0; i < aLen; i++) { match |= a[i] ^ b[i]; } return (match == 0); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/StandardStringDigester.java000066400000000000000000001160341360667575700312100ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; import org.jasypt.digest.config.DigesterConfig; import org.jasypt.digest.config.StringDigesterConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.normalization.Normalizer; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link StringDigester} interface. * This class lets the user specify the algorithm (and provider) to be used for * creating digests, the size of the salt to be applied, * the number of times the hash function will be applied (iterations) and * the salt generator to be used. *

*

* This class avoids byte-conversion problems related to the fact of * different platforms having different default charsets, and returns * digests in the form of BASE64-encoded or HEXADECIMAL ASCII Strings. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, salt size, iterations and salt generator can take values * in any of these ways: *

    *
  • Using its default values.
  • *
  • Setting a {@link org.jasypt.digest.config.DigesterConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setX(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a {@link org.jasypt.digest.config.DigesterConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to create digests, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
* Once a digester has been initialized, trying to * change its configuration * will result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* A digester may be used in two different ways: *

    *
  • For creating digests, by calling the digest method.
  • *
  • For matching digests, this is, checking whether a digest * corresponds adequately to a digest (as in password checking) or not, by * calling the matches method.
  • *
* The steps taken for creating digests are: *
    *
  1. The String message is converted to a byte array.
  2. *
  3. A salt of the specified size is generated (see * {@link org.jasypt.salt.SaltGenerator}).
  4. *
  5. The salt bytes are added to the message.
  6. *
  7. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  8. *
  9. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  10. *
  11. The result of the concatenation is encoded in BASE64 or HEXADECIMAL * and returned as an ASCII String.
  12. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed * with the same salt on a different message to check if both messages * match (all of which will be managed automatically by the * matches method). *

*

* To learn more about the mechanisms involved in digest creation, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.0 * * @author Daniel Fernández * */ public final class StandardStringDigester implements StringDigester { /** *

* Charset to be used to obtain "digestable" byte arrays from input Strings. * Set to UTF-8. *

*

* This charset has to be fixed to some value so that we avoid problems * with different platforms having different "default" charsets. *

*

* It is set to UTF-8 because it covers the whole spectrum of characters * representable in Java (which internally uses UTF-16), and avoids the * size penalty of UTF-16 (which will always use two bytes for representing * each character, even if it is an ASCII one). *

*

* Setting this value to UTF-8 does not mean that Strings that originally * come for, for example, an ISO-8859-1 input, will not be correcly * digested. It simply provides a way of "fixing" the way a String will * be converted into bytes for digesting. *

*/ public static final String MESSAGE_CHARSET = "UTF-8"; /** *

* Charset to be used for encoding the resulting digests. * Set to US-ASCII. *

*

* The result of digesting some bytes can be any other bytes, and so * the result of digesting, for example, some LATIN-1 valid String bytes, * can be bytes that may not conform a "valid" LATIN-1 String. *

*

* Because of this, digests are always encoded in BASE64 or * HEXADECIMAL after * being created, and this ensures that the * digests will make perfectly representable, safe ASCII Strings. Because * of this, the charset used to convert the digest bytes to the returned * String is set to US-ASCII. *

*/ public static final String DIGEST_CHARSET = "US-ASCII"; /** *

* Whether the Unicode normalization step should be ignored because of * legacy-compatibility issues. Defaults to FALSE (the normalization * step WILL be performed). *

*/ public static final boolean DEFAULT_UNICODE_NORMALIZATION_IGNORED = false; /** *

* Default type of String output. Set to BASE64. *

*/ public static final String DEFAULT_STRING_OUTPUT_TYPE = CommonUtils.STRING_OUTPUT_TYPE_BASE64; // The StandardByteDigester that will be internally used. private final StandardByteDigester byteDigester; // If the config object set is a StringDigesterConfig, it must be referenced private StringDigesterConfig stringDigesterConfig = null; // This variable holds whether the unicode normalization step should // be ignored or not (default = DO NOT ignore). private boolean unicodeNormalizationIgnored = DEFAULT_UNICODE_NORMALIZATION_IGNORED; // This variable holds the type of String output which will be done, // and also a boolean variable for faster comparison private String stringOutputType = DEFAULT_STRING_OUTPUT_TYPE; private boolean stringOutputTypeBase64 = true; // Prefix and suffix to be added to encryption results (if any) private String prefix = null; private String suffix = null; /* * Set of booleans which indicate whether the config or default values * have to be overriden because of the setX methods having been * called. */ private boolean unicodeNormalizationIgnoredSet = false; private boolean stringOutputTypeSet = false; private boolean prefixSet = false; private boolean suffixSet = false; // BASE64 encoder which will make sure the returned digests are // valid US-ASCII strings (if the user chooses BASE64 output). // The Bsae64 encoder is THREAD-SAFE private final Base64 base64; /** * Creates a new instance of StandardStringDigester. */ public StandardStringDigester() { super(); this.byteDigester = new StandardByteDigester(); this.base64 = new Base64(); } /* * Creates a new instance of StandardStringDigester using * the specified byte digester (constructor used for cloning) */ private StandardStringDigester(final StandardByteDigester standardByteDigester) { super(); this.byteDigester = standardByteDigester; this.base64 = new Base64(); } /** *

* Sets a {@link org.jasypt.digest.config.DigesterConfig} * or {@link StringDigesterConfig} object * for the digester. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Salt size
  • *
  • Hashing iterations
  • *
  • Salt generator
  • *
  • Use of Unicode normalization mechanisms * (only StringDigesterConfig)
  • *
  • Output type (base64, hexadecimal) * (only StringDigesterConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the DigesterConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final DigesterConfig config) { this.byteDigester.setConfig(config); if ((config != null) && (config instanceof StringDigesterConfig)) { this.stringDigesterConfig = (StringDigesterConfig) config; } } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.byteDigester.setAlgorithm(algorithm); } /** *

* Sets the size of the salt to be used to compute the digest. * This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* *

* If salt size is set to zero, then no salt will be used. *

* * @param saltSizeBytes the size of the salt to be used, in bytes. */ public void setSaltSizeBytes(final int saltSizeBytes) { this.byteDigester.setSaltSizeBytes(saltSizeBytes); } /** *

* Set the number of times the hash function will be applied recursively. *
* The hash function will be applied to its own results as many times as * specified: h(h(...h(x)...)) *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param iterations the number of iterations. */ public void setIterations(final int iterations) { this.byteDigester.setIterations(iterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.byteDigester.setSaltGenerator(saltGenerator); } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the digest algorithm. */ public void setProviderName(final String providerName) { this.byteDigester.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.byteDigester.setProvider(provider); } /** *

* Whether the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of salt before message) will be applied. *

* * @since 1.7 * * @param invertPositionOfSaltInMessageBeforeDigesting * whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). */ public synchronized void setInvertPositionOfSaltInMessageBeforeDigesting( final boolean invertPositionOfSaltInMessageBeforeDigesting) { this.byteDigester.setInvertPositionOfSaltInMessageBeforeDigesting(invertPositionOfSaltInMessageBeforeDigesting); } /** *

* Whether the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

*

* If this parameter is not explicitly set, the default behaviour * (insertion of plain salt before digest result) will be applied. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResults * whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). */ public synchronized void setInvertPositionOfPlainSaltInEncryptionResults( final boolean invertPositionOfPlainSaltInEncryptionResults) { this.byteDigester.setInvertPositionOfPlainSaltInEncryptionResults(invertPositionOfPlainSaltInEncryptionResults); } /** *

* Whether digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* If this parameter is not explicitly set, the default behaviour * (NOT lenient) will be applied. *

* * @since 1.7 * * @param useLenientSaltSizeCheck whether the digester will allow matching of * digests with different salt sizes than established or not (default * is false). */ public synchronized void setUseLenientSaltSizeCheck(final boolean useLenientSaltSizeCheck) { this.byteDigester.setUseLenientSaltSizeCheck(useLenientSaltSizeCheck); } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

* * @since 1.3 * * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public synchronized void setUnicodeNormalizationIgnored(final boolean unicodeNormalizationIgnored) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; this.unicodeNormalizationIgnoredSet = true; } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @since 1.3 * * @param stringOutputType the string output type. */ public synchronized void setStringOutputType(final String stringOutputType) { CommonUtils.validateNotEmpty(stringOutputType, "String output type cannot be set empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); this.stringOutputTypeSet = true; } /** *

* Sets the prefix to be added at the beginning of encryption results, and also to * be expected at the beginning of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* By default, no prefix will be added to encryption results. *

* * @since 1.7 * * @param prefix the prefix to be set */ public synchronized void setPrefix(final String prefix) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.prefix = prefix; this.prefixSet = true; } /** *

* Sets the suffix to be added at the end of encryption results, and also to * be expected at the end of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* By default, no suffix will be added to encryption results. *

* * @since 1.7 * * @param suffix the suffix to be set */ public synchronized void setSuffix(final String suffix) { if (isInitialized()) { throw new AlreadyInitializedException(); } this.suffix = suffix; this.suffixSet = true; } /* * Clone this digester. */ StandardStringDigester cloneDigester() { // Check initialization if (!isInitialized()) { initialize(); } final StandardStringDigester cloned = new StandardStringDigester(this.byteDigester.cloneDigester()); cloned.setPrefix(this.prefix); cloned.setSuffix(this.suffix); if (CommonUtils.isNotEmpty(this.stringOutputType)) { cloned.setStringOutputType(this.stringOutputType); } cloned.setUnicodeNormalizationIgnored(this.unicodeNormalizationIgnored); return cloned; } /** *

* Returns true if the digester has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When digest or matches are called for the * first time, if initialize has not been called before.
  • *
*

* Once a digester has been initialized, trying to * change its configuration will result in an * AlreadyInitializedException * being thrown. *

* * @return true if the digester has already been initialized, false if * not. */ public boolean isInitialized() { return this.byteDigester.isInitialized(); } /** *

* Initialize the digester. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the digester with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered.
  2. *
  3. Then, if a * {@link org.jasypt.digest.config.DigesterConfig} object * has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the digester itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* Once a digester has been initialized, trying to * change its configuration will result in an * AlreadyInitializedException * being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). * */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.isInitialized()) { /* * If a StringDigesterConfig object has been set, we need to * consider the values it returns (if, for each value, the * corresponding "setX" method has not been called). */ if (this.stringDigesterConfig != null) { final Boolean configUnicodeNormalizationIgnored = this.stringDigesterConfig.isUnicodeNormalizationIgnored(); final String configStringOutputType = this.stringDigesterConfig.getStringOutputType(); final String configPrefix = this.stringDigesterConfig.getPrefix(); final String configSuffix = this.stringDigesterConfig.getSuffix(); this.unicodeNormalizationIgnored = ((this.unicodeNormalizationIgnoredSet) || (configUnicodeNormalizationIgnored == null))? this.unicodeNormalizationIgnored : configUnicodeNormalizationIgnored.booleanValue(); this.stringOutputType = ((this.stringOutputTypeSet) || (configStringOutputType == null))? this.stringOutputType : configStringOutputType; this.prefix = ((this.prefixSet) || (configPrefix == null))? this.prefix : configPrefix; this.suffix = ((this.suffixSet) || (configSuffix == null))? this.suffix : configSuffix; } this.stringOutputTypeBase64 = (CommonUtils.STRING_OUTPUT_TYPE_BASE64. equalsIgnoreCase(this.stringOutputType)); this.byteDigester.initialize(); } } /** *

* Performs a digest operation on a String message. *

*

* The steps taken for creating the digest are: *

    *
  1. The String message is converted to a byte array.
  2. *
  3. A salt of the specified size is generated (see * {@link org.jasypt.salt.SaltGenerator}).
  4. *
  5. The salt bytes are added to the message.
  6. *
  7. The hash function is applied to the salt and message altogether, * and then to the * results of the function itself, as many times as specified * (iterations).
  8. *
  9. If specified by the salt generator (see * {@link org.jasypt.salt.SaltGenerator#includePlainSaltInEncryptionResults()}), * the undigested salt and the final result of the hash * function are concatenated and returned as a result.
  10. *
  11. The result of the concatenation is encoded in BASE64 (default) * or HEXADECIMAL * and returned as an ASCII String.
  12. *
* Put schematically in bytes: *
    *
  • * DIGEST = |S|..(ssb)..|S|X|X|X|...|X| *
      *
    • S: salt bytes (plain, not digested). (OPTIONAL).
    • *
    • ssb: salt size in bytes.
    • *
    • X: bytes resulting from hashing (see below).
    • *
    *
  • *
  • * |X|X|X|...|X| = * H(H(H(..(it)..H(Z|Z|Z|...|Z|)))) *
      *
    • H: Hash function (algorithm).
    • *
    • it: Number of iterations.
    • *
    • Z: Input for hashing (see below).
    • *
    *
  • *
  • * |Z|Z|Z|...|Z| = * |S|..(ssb)..|S|M|M|M...|M| *
      *
    • S: salt bytes (plain, not digested).
    • *
    • ssb: salt size in bytes.
    • *
    • M: message bytes.
    • *
    *
  • *
*

*

* If a random salt generator is used, two digests created for the same * message will always be different * (except in the case of random salt coincidence). * Because of this, in this case the result of the digest method * will contain both the undigested salt and the digest of the * (salt + message), so that another digest operation can be performed * with the same salt on a different message to check if both messages * match (all of which will be managed automatically by the * matches method). *

* * @param message the String to be digested * @return the digest result * @throws EncryptionOperationNotPossibleException if the digest operation * fails, ommitting any further information about the cause for * security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public String digest(final String message) { if (message == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } try { // Normalize Unicode message to NFC form String normalizedMessage = null; if (! this.unicodeNormalizationIgnored) { normalizedMessage = Normalizer.normalizeToNfc(message); } else { normalizedMessage = message; } // The input String is converted into bytes using MESSAGE_CHARSET // as a fixed charset to avoid problems with different platforms // having different default charsets (see MESSAGE_CHARSET doc). final byte[] messageBytes = normalizedMessage.getBytes(MESSAGE_CHARSET); // The StandardByteDigester does its job. byte[] digest = this.byteDigester.digest(messageBytes); // We build the result variable final StringBuffer result = new StringBuffer(); if (this.prefix != null) { // Prefix is added result.append(this.prefix); } // We encode the result in BASE64 or HEXADECIMAL so that we obtain // the safest result String possible. if (this.stringOutputTypeBase64) { digest = this.base64.encode(digest); result.append(new String(digest, DIGEST_CHARSET)); } else { result.append(CommonUtils.toHexadecimal(digest)); } if (this.suffix != null) { // Suffix is added result.append(this.suffix); } return result.toString(); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If digest fails, it is more secure not to return any information // about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Checks a message against a given digest. *

*

* This method tells whether a message corresponds to a specific digest * or not by getting the salt with which the digest was created and * applying it to a digest operation performed on the message. If * new and existing digest match, the message is said to match the digest. *

*

* This method will be used, for instance, for password checking in * authentication processes. *

*

* A null message will only match a null digest. *

* * @param message the message to be compared to the digest. * @param digest the digest. * @return true if the specified message matches the digest, false * if not. * @throws EncryptionOperationNotPossibleException if the digest matching * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, if the digest algorithm chosen * cannot be used). */ public boolean matches(final String message, final String digest) { String processedDigest = digest; if (processedDigest != null) { if (this.prefix != null) { if (!processedDigest.startsWith(this.prefix)) { throw new EncryptionOperationNotPossibleException( "Digest does not start with required prefix \"" + this.prefix + "\""); } processedDigest = processedDigest.substring(this.prefix.length()); } if (this.suffix != null) { if (!processedDigest.endsWith(this.suffix)) { throw new EncryptionOperationNotPossibleException( "Digest does not end with required suffix \"" + this.suffix + "\""); } processedDigest = processedDigest.substring(0, processedDigest.length() - this.suffix.length()); } } if (message == null) { return (processedDigest == null); } else if (processedDigest == null) { return false; } // Check initialization if (!isInitialized()) { initialize(); } try { // Normalize Unicode message to NFC form String normalizedMessage = null; if (! this.unicodeNormalizationIgnored) { normalizedMessage = Normalizer.normalizeToNfc(message); } else { normalizedMessage = message; } // We get a valid byte array from the message, in the // fixed MESSAGE_CHARSET that the digest operations use. final byte[] messageBytes = normalizedMessage.getBytes(MESSAGE_CHARSET); // The BASE64 or HEXADECIMAL encoding is reversed and the digest // is converted into a byte array. byte[] digestBytes = null; if (this.stringOutputTypeBase64) { // The digest must be a US-ASCII String BASE64-encoded digestBytes = processedDigest.getBytes(DIGEST_CHARSET); digestBytes = this.base64.decode(digestBytes); } else { digestBytes = CommonUtils.fromHexadecimal(processedDigest); } // The StandardByteDigester is asked to match message to digest. return this.byteDigester.matches(messageBytes, digestBytes); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If digest fails, it is more secure not to return any information // about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/StringDigester.java000066400000000000000000000033451360667575700275270ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; /** *

* Common interface for all digesters which receive a String message and * return a String digest. *

*

* For a default implementation, see {@link StandardStringDigester}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface StringDigester { /** *

* Create a digest of the input message. *

* * @param message the message to be digested * @return the digest */ public String digest(String message); /** *

* Check whether a message matches a digest, managing aspects like * salt, hashing iterations, etc. (if applicable). *

* * @param message the message to check * @param digest the digest to check * @return TRUE if the message matches the digest, FALSE if not. */ public boolean matches(String message, String digest); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/000077500000000000000000000000001360667575700251675ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/DigesterConfig.java000066400000000000000000000237711360667575700307400ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; import java.security.Provider; import org.jasypt.salt.SaltGenerator; /** *

* Common interface for config classes applicable to * {@link org.jasypt.digest.StandardByteDigester}, * {@link org.jasypt.digest.StandardStringDigester}, * {@link org.jasypt.digest.PooledByteDigester} or * {@link org.jasypt.digest.PooledStringDigester} * objects. *

*

* This interface lets the user create new DigesterConfig * classes which retrieve values for this parameters from different * (and maybe more secure) sources (remote servers, LDAP, other databases...), * and do this transparently for the digester object. *

*

* The config objects passed to a digester will only be queried once * for each configuration parameter, and this will happen * during the initialization of the digester object. *

*

* For a default implementation, see {@link SimpleDigesterConfig}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface DigesterConfig { /** *

* Returns the name of an algorithm to be used for hashing, like "MD5" or * "SHA-1". *

*

* This algorithm has to be supported by your Java Virtual Machine, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If this method returns null, the digester will ignore the config object * when deciding the algorithm to be used. *

* * @return the name of the algorithm to be used, or null if this object * will not want to set an algorithm. See Appendix A * in the Java * Cryptography Architecture API Specification & * Reference * for information about standard algorithm names. */ public String getAlgorithm(); /** *

* Returns the size of the salt to be used to compute the digest. * This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

*

* If salt size is set to zero, then no salt will be used. *

*

* If this method returns null, the digester will ignore the config object * when deciding the size of the salt to be used. *

* * @return the size of the salt to be used, in bytes, or null if * this object will not want to set a size for salt. */ public Integer getSaltSizeBytes(); /** *

* Returns the number of times the hash function will be applied recursively. *
* The hash function will be applied to its own results as many times as * specified: h(h(...h(x)...)) *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

*

* If this method returns null, the digester will ignore the config object * when deciding the number of hashing iterations. *

* * @return the number of iterations, or null if this object will not want * to set the number of iterations. */ public Integer getIterations(); /** *

* Returns a {@link SaltGenerator} implementation to be used by the digester. *

*

* If this method returns null, the digester will ignore the config object * when deciding the salt generator to be used. *

* * @since 1.2 * * @return the salt generator, or null if this object will not want to set * a specific SaltGenerator implementation. */ public SaltGenerator getSaltGenerator(); /** *

* Returns the name of the java.security.Provider implementation * to be used by the digester for obtaining the digest algorithm. This * provider must have been registered beforehand. *

*

* If this method returns null, the digester will ignore this parameter * when deciding the name of the security provider to be used. *

*

* If this method does not return null, and neither does {@link #getProvider()}, * providerName will be ignored, and the provider object returned * by getProvider() will be used. *

* * @since 1.3 * * @return the name of the security provider to be used. */ public String getProviderName(); /** *

* Returns the java.security.Provider implementation object * to be used by the digester for obtaining the digest algorithm. *

*

* If this method returns null, the digester will ignore this parameter * when deciding the security provider object to be used. *

*

* If this method does not return null, and neither does {@link #getProviderName()}, * providerName will be ignored, and the provider object returned * by getProvider() will be used. *

*

* The provider returned by this method does not need to be * registered beforehand, and its use will not result in its * being registered. *

* * @since 1.3 * * @return the security provider object to be asked for the digest * algorithm. */ public Provider getProvider(); /** *

* Returns Boolean.TRUE if the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

* * @since 1.7 * * @return whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). If null is returned, the default * behaviour will be applied. */ public Boolean getInvertPositionOfSaltInMessageBeforeDigesting(); /** *

* Returns Boolean.TRUE if the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

* * @since 1.7 * * @return whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). If null is returned, the default behaviour will be * applied. */ public Boolean getInvertPositionOfPlainSaltInEncryptionResults(); /** *

* Returns Boolean.TRUE if digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* Default is FALSE. *

* * @since 1.7 * * @return whether the digester will allow matching of digests with different * salt sizes than established or not (default is false). */ public Boolean getUseLenientSaltSizeCheck(); /** *

* Get the size of the pool of digesters to be created. *

*

* This parameter will be ignored if used with a non-pooled digester. *

* * @since 1.7 * * @return the size of the pool to be used if this configuration is used with a * pooled digester */ public Integer getPoolSize(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/EnvironmentDigesterConfig.java000066400000000000000000000723051360667575700331620ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.salt.SaltGenerator; /** *

* Implementation for {@link DigesterConfig} which can retrieve configuration * values from environment variables or system properties. *

*

* The name of the environment variable or system property (JVM property) to * query for each parameter can be set with its corresponding * setXEnvName or setXSysProperty method. *

*

* As this class extends {@link SimpleDigesterConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its value is not configured * in any way, a null value will be returned by the * corresponding getX method. *

* * @since 1.1 * * @author Daniel Fernández * */ public class EnvironmentDigesterConfig extends SimpleDigesterConfig { private String algorithmEnvName = null; private String iterationsEnvName = null; private String saltSizeBytesEnvName = null; private String saltGeneratorClassNameEnvName = null; private String providerNameEnvName = null; private String providerClassNameEnvName = null; private String invertPositionOfSaltInMessageBeforeDigestingEnvName = null; private String invertPositionOfPlainSaltInEncryptionResultsEnvName = null; private String useLenientSaltSizeCheckEnvName = null; private String poolSizeEnvName = null; private String algorithmSysPropertyName = null; private String iterationsSysPropertyName = null; private String saltSizeBytesSysPropertyName = null; private String saltGeneratorClassNameSysPropertyName = null; private String providerNameSysPropertyName = null; private String providerClassNameSysPropertyName = null; private String invertPositionOfSaltInMessageBeforeDigestingSysPropertyName = null; private String invertPositionOfPlainSaltInEncryptionResultsSysPropertyName = null; private String useLenientSaltSizeCheckSysPropertyName = null; private String poolSizeSysPropertyName = null; /** *

* Creates a new EnvironmentDigesterConfig instance. *

*/ public EnvironmentDigesterConfig() { super(); } /** * Retrieve the name of the environment variable which value has been * loaded as the algorithm. * * @return the name of the variable */ public String getAlgorithmEnvName() { return this.algorithmEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the algorithm. * * @param algorithmEnvName the name of the environment variable */ public void setAlgorithmEnvName(final String algorithmEnvName) { this.algorithmEnvName = algorithmEnvName; if (algorithmEnvName == null) { super.setAlgorithm(null); } else { this.algorithmSysPropertyName = null; super.setAlgorithm(System.getenv(algorithmEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the algorithm. * * @return the name of the property */ public String getAlgorithmSysPropertyName() { return this.algorithmSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the algorithm. * * @param algorithmSysPropertyName the name of the property */ public void setAlgorithmSysPropertyName(final String algorithmSysPropertyName) { this.algorithmSysPropertyName = algorithmSysPropertyName; if (algorithmSysPropertyName == null) { super.setAlgorithm(null); } else { this.algorithmEnvName = null; super.setAlgorithm(System.getProperty(algorithmSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the iteration count. * * @return the name of the variable */ public String getIterationsEnvName() { return this.iterationsEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the iteration count. * * @param iterationsEnvName the name of the environment variable */ public void setIterationsEnvName(String iterationsEnvName) { this.iterationsEnvName = iterationsEnvName; if (iterationsEnvName == null) { super.setIterations((String)null); } else { this.iterationsSysPropertyName = null; super.setIterations(System.getenv(iterationsEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the iteration count. * * @return the name of the property */ public String getIterationsSysPropertyName() { return this.iterationsSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the iteration count. * * @param iterationsSysPropertyName the name of the property */ public void setIterationsSysPropertyName(final String iterationsSysPropertyName) { this.iterationsSysPropertyName = iterationsSysPropertyName; if (iterationsSysPropertyName == null) { super.setIterations((String)null); } else { this.iterationsEnvName = null; super.setIterations(System.getProperty(iterationsSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the salt size in bytes. * * @return the name of the variable */ public String getSaltSizeBytesEnvName() { return this.saltSizeBytesEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the salt size in bytes. * * @param saltSizeBytesEnvName the name of the environment variable */ public void setSaltSizeBytesEnvName(final String saltSizeBytesEnvName) { this.saltSizeBytesEnvName = saltSizeBytesEnvName; if (saltSizeBytesEnvName == null) { super.setSaltSizeBytes((String)null); } else { this.saltSizeBytesSysPropertyName = null; super.setSaltSizeBytes(System.getenv(saltSizeBytesEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the salt size in bytes. * * @return the name of the property */ public String getSaltSizeBytesSysPropertyName() { return this.saltSizeBytesSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the salt size in bytes. * * @param saltSizeBytesSysPropertyName the name of the property */ public void setSaltSizeBytesSysPropertyName(final String saltSizeBytesSysPropertyName) { this.saltSizeBytesSysPropertyName = saltSizeBytesSysPropertyName; if (saltSizeBytesSysPropertyName == null) { super.setSaltSizeBytes((Integer)null); } else { this.saltSizeBytesEnvName = null; super.setSaltSizeBytes( System.getProperty(saltSizeBytesSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the salt generator class name. * * @since 1.3 * * @return the name of the variable */ public String getSaltGeneratorClassNameEnvName() { return this.saltGeneratorClassNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the salt generator class name. *

*

* The salt generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the digester. *

* * @since 1.3 * * @param saltGeneratorClassNameEnvName the name of the environment variable */ public void setSaltGeneratorClassNameEnvName(final String saltGeneratorClassNameEnvName) { this.saltGeneratorClassNameEnvName = saltGeneratorClassNameEnvName; if (saltGeneratorClassNameEnvName == null) { super.setSaltGenerator(null); } else { this.saltGeneratorClassNameSysPropertyName = null; final String saltGeneratorClassName = System.getenv(saltGeneratorClassNameEnvName); super.setSaltGeneratorClassName(saltGeneratorClassName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the salt generator class name. * * @since 1.3 * * @return the name of the property */ public String getSaltGeneratorClassNameSysPropertyName() { return this.saltGeneratorClassNameSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the salt generator class name. *

*

* The salt generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the digester. *

* * @since 1.3 * * @param saltGeneratorClassNameSysPropertyName the name of the property */ public void setSaltGeneratorClassNameSysPropertyName(final String saltGeneratorClassNameSysPropertyName) { this.saltGeneratorClassNameSysPropertyName = saltGeneratorClassNameSysPropertyName; if (saltGeneratorClassNameSysPropertyName == null) { super.setSaltGenerator(null); } else { this.saltGeneratorClassNameEnvName = null; final String saltGeneratorClassName = System.getProperty(saltGeneratorClassNameSysPropertyName); super.setSaltGeneratorClassName(saltGeneratorClassName); } } /** * Retrieve the name of the environment variable which value has been * loaded as the provider name. * * @since 1.3 * * @return the name of the variable */ public String getProviderNameEnvName() { return this.providerNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the provider name. *

* * @since 1.3 * * @param providerNameEnvName the name of the environment variable */ public void setProviderNameEnvName(final String providerNameEnvName) { this.providerNameEnvName = providerNameEnvName; if (providerNameEnvName == null) { super.setProviderName(null); } else { this.providerNameSysPropertyName = null; super.setProviderName(System.getenv(providerNameEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the provider name. * * @since 1.3 * * @return the name of the property */ public String getProviderNameSysPropertyName() { return this.providerNameSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the provider name. * * @since 1.3 * * @param providerNameSysPropertyName the name of the property */ public void setProviderNameSysPropertyName(final String providerNameSysPropertyName) { this.providerNameSysPropertyName = providerNameSysPropertyName; if (providerNameSysPropertyName == null) { super.setProviderName(null); } else { this.providerNameEnvName = null; super.setProviderName(System.getProperty(providerNameSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the provider class name. * * @since 1.3 * * @return the name of the variable */ public String getProviderClassNameEnvName() { return this.providerClassNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the provider class name. *

*

* The provider class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the digester. *

* * @since 1.3 * * @param providerClassNameEnvName the name of the environment variable */ public void setProviderClassNameEnvName(final String providerClassNameEnvName) { this.providerClassNameEnvName = providerClassNameEnvName; if (providerClassNameEnvName == null) { super.setProvider(null); } else { this.providerClassNameSysPropertyName = null; final String providerClassName = System.getenv(providerClassNameEnvName); super.setProviderClassName(providerClassName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the provider class name. * * @since 1.3 * * @return the name of the property */ public String getProviderClassNameSysPropertyName() { return this.providerClassNameSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the provider class name. *

*

* The provider class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the digester. *

* * @since 1.3 * * @param providerClassNameSysPropertyName the name of the property */ public void setProviderClassNameSysPropertyName(final String providerClassNameSysPropertyName) { this.providerClassNameSysPropertyName = providerClassNameSysPropertyName; if (providerClassNameSysPropertyName == null) { super.setProvider(null); } else { this.providerClassNameEnvName = null; final String providerClassName = System.getProperty(providerClassNameSysPropertyName); super.setProviderClassName(providerClassName); } } /** * Retrieve the name of the environment variable which value has been * loaded as the value for the invertPositionOfSaltInMessageBeforeDigesting * property. * * @since 1.7 * * @return the name of the variable */ public String getInvertPositionOfSaltInMessageBeforeDigestingEnvName() { return this.invertPositionOfSaltInMessageBeforeDigestingEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the invertPositionOfSaltInMessageBeforeDigesting * property. *

* * @since 1.7 * * @param invertPositionOfSaltInMessageBeforeDigestingEnvName the name of the environment variable */ public void setInvertPositionOfSaltInMessageBeforeDigestingEnvName(final String invertPositionOfSaltInMessageBeforeDigestingEnvName) { this.invertPositionOfSaltInMessageBeforeDigestingEnvName = invertPositionOfSaltInMessageBeforeDigestingEnvName; if (invertPositionOfSaltInMessageBeforeDigestingEnvName == null) { super.setInvertPositionOfSaltInMessageBeforeDigesting(null); } else { this.invertPositionOfSaltInMessageBeforeDigestingSysPropertyName = null; super.setInvertPositionOfSaltInMessageBeforeDigesting( CommonUtils.getStandardBooleanValue( System.getenv(invertPositionOfSaltInMessageBeforeDigestingEnvName))); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the value for the invertPositionOfSaltInMessageBeforeDigesting * property. * * @since 1.7 * * @return the name of the property */ public String getInvertPositionOfSaltInMessageBeforeDigestingSysPropertyName() { return this.invertPositionOfSaltInMessageBeforeDigestingSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the invertPositionOfSaltInMessageBeforeDigesting * property. *

* * @since 1.7 * * @param invertPositionOfSaltInMessageBeforeDigestingSysPropertyName the name of the property */ public void setInvertPositionOfSaltInMessageBeforeDigestingSysPropertyName(final String invertPositionOfSaltInMessageBeforeDigestingSysPropertyName) { this.invertPositionOfSaltInMessageBeforeDigestingSysPropertyName = invertPositionOfSaltInMessageBeforeDigestingSysPropertyName; if (invertPositionOfSaltInMessageBeforeDigestingSysPropertyName == null) { super.setInvertPositionOfSaltInMessageBeforeDigesting(null); } else { this.invertPositionOfSaltInMessageBeforeDigestingEnvName = null; super.setInvertPositionOfSaltInMessageBeforeDigesting( CommonUtils.getStandardBooleanValue( System.getProperty(invertPositionOfSaltInMessageBeforeDigestingSysPropertyName))); } } /** * Retrieve the name of the environment variable which value has been * loaded as the value for the invertPositionOfPlainSaltInEncryptionResults * property. * * @since 1.7 * * @return the name of the variable */ public String getInvertPositionOfPlainSaltInEncryptionResultsEnvName() { return this.invertPositionOfPlainSaltInEncryptionResultsEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the invertPositionOfPlainSaltInEncryptionResults * property. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResultsEnvName the name of the environment variable */ public void setInvertPositionOfPlainSaltInEncryptionResultsEnvName(final String invertPositionOfPlainSaltInEncryptionResultsEnvName) { this.invertPositionOfPlainSaltInEncryptionResultsEnvName = invertPositionOfPlainSaltInEncryptionResultsEnvName; if (invertPositionOfPlainSaltInEncryptionResultsEnvName == null) { super.setInvertPositionOfPlainSaltInEncryptionResults(null); } else { this.invertPositionOfPlainSaltInEncryptionResultsSysPropertyName = null; super.setInvertPositionOfPlainSaltInEncryptionResults( CommonUtils.getStandardBooleanValue( System.getenv(invertPositionOfPlainSaltInEncryptionResultsEnvName))); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the value for the invertPositionOfPlainSaltInEncryptionResults * property. * * @since 1.7 * * @return the name of the property */ public String getInvertPositionOfPlainSaltInEncryptionResultsSysPropertyName() { return this.invertPositionOfPlainSaltInEncryptionResultsSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the invertPositionOfPlainSaltInEncryptionResults * property. *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResultsSysPropertyName the name of the property */ public void setInvertPositionOfPlainSaltInEncryptionResultsSysPropertyName(final String invertPositionOfPlainSaltInEncryptionResultsSysPropertyName) { this.invertPositionOfPlainSaltInEncryptionResultsSysPropertyName = invertPositionOfPlainSaltInEncryptionResultsSysPropertyName; if (invertPositionOfPlainSaltInEncryptionResultsSysPropertyName == null) { super.setInvertPositionOfPlainSaltInEncryptionResults(null); } else { this.invertPositionOfPlainSaltInEncryptionResultsEnvName = null; super.setInvertPositionOfPlainSaltInEncryptionResults( CommonUtils.getStandardBooleanValue( System.getProperty(invertPositionOfPlainSaltInEncryptionResultsSysPropertyName))); } } /** * Retrieve the name of the environment variable which value has been * loaded as the value for the useLenientSaltSizeCheck * property. * * @since 1.7 * * @return the name of the variable */ public String getUseLenientSaltSizeCheckEnvName() { return this.useLenientSaltSizeCheckEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the useLenientSaltSizeCheck * property. *

* * @since 1.7 * * @param useLenientSaltSizeCheckEnvName the name of the environment variable */ public void setUseLenientSaltSizeCheckEnvName(final String useLenientSaltSizeCheckEnvName) { this.useLenientSaltSizeCheckEnvName = useLenientSaltSizeCheckEnvName; if (useLenientSaltSizeCheckEnvName == null) { super.setUseLenientSaltSizeCheck(null); } else { this.useLenientSaltSizeCheckSysPropertyName = null; super.setUseLenientSaltSizeCheck( CommonUtils.getStandardBooleanValue( System.getenv(useLenientSaltSizeCheckEnvName))); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the value for the useLenientSaltSizeCheck * property. * * @since 1.7 * * @return the name of the property */ public String getUseLenientSaltSizeCheckSysPropertyName() { return this.useLenientSaltSizeCheckSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the useLenientSaltSizeCheck * property. *

* * @since 1.7 * * @param useLenientSaltSizeCheckSysPropertyName the name of the property */ public void setUseLenientSaltSizeCheckSysPropertyName(final String useLenientSaltSizeCheckSysPropertyName) { this.useLenientSaltSizeCheckSysPropertyName = useLenientSaltSizeCheckSysPropertyName; if (useLenientSaltSizeCheckSysPropertyName == null) { super.setUseLenientSaltSizeCheck(null); } else { this.useLenientSaltSizeCheckEnvName = null; super.setUseLenientSaltSizeCheck( CommonUtils.getStandardBooleanValue( System.getProperty(useLenientSaltSizeCheckSysPropertyName))); } } /** * Retrieve the name of the environment variable which value has been * loaded as the value for the poolSize * property. * * @since 1.7 * * @return the name of the variable */ public String getPoolSizeEnvName() { return this.poolSizeEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the poolSize * property. *

* * @since 1.7 * * @param poolSizeEnvName the name of the environment variable */ public void setPoolSizeEnvName(final String poolSizeEnvName) { this.poolSizeEnvName = poolSizeEnvName; if (poolSizeEnvName == null) { super.setPoolSize((String)null); } else { this.poolSizeSysPropertyName = null; super.setPoolSize(System.getenv(poolSizeEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the value for the poolSize * property. * * @since 1.7 * * @return the name of the property */ public String getPoolSizeSysPropertyName() { return this.poolSizeSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the useLenientSaltSizeCheck * property. *

* * @since 1.7 * * @param poolSizeSysPropertyName the name of the property */ public void setPoolSizeSysPropertyName(final String poolSizeSysPropertyName) { this.poolSizeSysPropertyName = poolSizeSysPropertyName; if (poolSizeSysPropertyName == null) { super.setPoolSize((String)null); } else { this.poolSizeEnvName = null; super.setPoolSize(System.getProperty(poolSizeSysPropertyName)); } } public void setAlgorithm(final String algorithm) { this.algorithmEnvName = null; this.algorithmSysPropertyName = null; super.setAlgorithm(algorithm); } public void setIterations(final Integer iterations) { this.iterationsEnvName = null; this.iterationsSysPropertyName = null; super.setIterations(iterations); } public void setIterations(final String iterations) { this.iterationsEnvName = null; this.iterationsSysPropertyName = null; super.setIterations(iterations); } public void setSaltSizeBytes(final Integer saltSizeBytes) { this.saltSizeBytesEnvName = null; this.saltSizeBytesSysPropertyName = null; super.setSaltSizeBytes(saltSizeBytes); } public void setSaltSizeBytes(final String saltSizeBytes) { this.saltSizeBytesEnvName = null; this.saltSizeBytesSysPropertyName = null; super.setSaltSizeBytes(saltSizeBytes); } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGeneratorClassNameEnvName = null; this.saltGeneratorClassNameSysPropertyName = null; super.setSaltGenerator(saltGenerator); } public void setSaltGeneratorClassName(final String saltGeneratorClassName) { this.saltGeneratorClassNameEnvName = null; this.saltGeneratorClassNameSysPropertyName = null; super.setSaltGeneratorClassName(saltGeneratorClassName); } public void setProviderName(final String providerName) { this.providerNameEnvName = null; this.providerNameSysPropertyName = null; super.setProviderName(providerName); } public void setProvider(final Provider provider) { this.providerClassNameEnvName = null; this.providerClassNameSysPropertyName = null; super.setProvider(provider); } public void setProviderClassName(final String providerClassName) { this.providerClassNameEnvName = null; this.providerClassNameSysPropertyName = null; super.setProviderClassName(providerClassName); } public void setInvertPositionOfPlainSaltInEncryptionResults(final Boolean invertPositionOfPlainSaltInEncryptionResults) { this.invertPositionOfPlainSaltInEncryptionResultsEnvName = null; this.invertPositionOfPlainSaltInEncryptionResultsSysPropertyName = null; super.setInvertPositionOfPlainSaltInEncryptionResults(invertPositionOfPlainSaltInEncryptionResults); } public void setInvertPositionOfSaltInMessageBeforeDigesting(final Boolean invertPositionOfSaltInMessageBeforeDigesting) { this.invertPositionOfSaltInMessageBeforeDigestingEnvName = null; this.invertPositionOfSaltInMessageBeforeDigestingSysPropertyName = null; super.setInvertPositionOfSaltInMessageBeforeDigesting(invertPositionOfSaltInMessageBeforeDigesting); } public void setUseLenientSaltSizeCheck(final Boolean useLenientSaltSizeCheck) { this.useLenientSaltSizeCheckEnvName = null; this.useLenientSaltSizeCheckSysPropertyName = null; super.setUseLenientSaltSizeCheck(useLenientSaltSizeCheck); } public void setPoolSize(final Integer poolSize) { this.poolSizeEnvName = null; this.poolSizeSysPropertyName = null; super.setPoolSize(poolSize); } public void setPoolSize(final String poolSize) { this.poolSizeEnvName = null; this.poolSizeSysPropertyName = null; super.setPoolSize(poolSize); } } EnvironmentStringDigesterConfig.java000066400000000000000000000405571360667575700342760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; import org.jasypt.commons.CommonUtils; /** *

* Implementation for {@link StringDigesterConfig} which can retrieve configuration * values from environment variables or system properties. *

*

* The name of the environment variable or system property (JVM property) to * query for each parameter can be set with its corresponding * setXEnvName or setXSysProperty method. *

*

* As this class extends {@link SimpleDigesterConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its value is not configured * in any way, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class EnvironmentStringDigesterConfig extends EnvironmentDigesterConfig implements StringDigesterConfig { private Boolean unicodeNormalizationIgnored = null; private String stringOutputType = null; private String prefix = null; private String suffix = null; private String unicodeNormalizationIgnoredEnvName = null; private String stringOutputTypeEnvName = null; private String prefixEnvName = null; private String suffixEnvName = null; private String unicodeNormalizationIgnoredSysPropertyName = null; private String stringOutputTypeSysPropertyName = null; private String prefixSysPropertyName = null; private String suffixSysPropertyName = null; /** *

* Creates a new EnvironmentStringDigesterConfig instance. *

*/ public EnvironmentStringDigesterConfig() { super(); } /** * Retrieve the name of the environment variable which value has been * loaded as a value for the "unicode normalization ignored" parameter. * * @return the name of the variable */ public String getUnicodeNormalizationIgnoredEnvName() { return this.unicodeNormalizationIgnoredEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the "unicode normalization ignored" parameter. * * @param unicodeNormalizationIgnoredEnvName the name of the environment * variable */ public void setUnicodeNormalizationIgnoredEnvName(final String unicodeNormalizationIgnoredEnvName) { this.unicodeNormalizationIgnoredEnvName = unicodeNormalizationIgnoredEnvName; if (unicodeNormalizationIgnoredEnvName == null) { this.unicodeNormalizationIgnored = null; } else { this.unicodeNormalizationIgnoredSysPropertyName = null; final String unicodeNormalizationIgnoredValue = System.getenv(unicodeNormalizationIgnoredEnvName); if (unicodeNormalizationIgnoredValue != null) { this.unicodeNormalizationIgnored = CommonUtils.getStandardBooleanValue( unicodeNormalizationIgnoredValue); } else { this.unicodeNormalizationIgnored = null; } } } /** * Retrieve the name of the JVM system property which value has been * loaded as a value for the "unicode normalization ignored" parameter. * * @return the name of the property */ public String getUnicodeNormalizationIgnoredSysPropertyName() { return this.unicodeNormalizationIgnoredSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load a value for the "unicode normalization ignored" parameter. * * @param unicodeNormalizationIgnoredSysPropertyName the name of the property */ public void setUnicodeNormalizationIgnoredSysPropertyName(final String unicodeNormalizationIgnoredSysPropertyName) { this.unicodeNormalizationIgnoredSysPropertyName = unicodeNormalizationIgnoredSysPropertyName; if (unicodeNormalizationIgnoredSysPropertyName == null) { this.unicodeNormalizationIgnored = null; } else { this.unicodeNormalizationIgnoredEnvName = null; final String unicodeNormalizationIgnoredValue = System.getProperty(unicodeNormalizationIgnoredSysPropertyName); if (unicodeNormalizationIgnoredValue != null) { this.unicodeNormalizationIgnored = CommonUtils.getStandardBooleanValue( unicodeNormalizationIgnoredValue); } else { this.unicodeNormalizationIgnored = null; } } } /** * Retrieve the name of the environment variable which value has been * loaded as the String output type. * * @return the name of the variable */ public String getStringOutputTypeEnvName() { return this.stringOutputTypeEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the String output type. * * @param stringOutputTypeEnvName the name of the environment variable */ public void setStringOutputTypeEnvName(final String stringOutputTypeEnvName) { this.stringOutputTypeEnvName = stringOutputTypeEnvName; if (stringOutputTypeEnvName == null) { this.stringOutputType = null; } else { this.stringOutputTypeSysPropertyName = null; this.stringOutputType = CommonUtils.getStandardStringOutputType( System.getenv(stringOutputTypeEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the String output type. * * @return the name of the property */ public String getStringOutputTypeSysPropertyName() { return this.stringOutputTypeSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the String output type. * * @param stringOutputTypeSysPropertyName the name of the property */ public void setStringOutputTypeSysPropertyName(final String stringOutputTypeSysPropertyName) { this.stringOutputTypeSysPropertyName = stringOutputTypeSysPropertyName; if (stringOutputTypeSysPropertyName == null) { this.stringOutputType = null; } else { this.stringOutputTypeEnvName = null; this.stringOutputType = CommonUtils.getStandardStringOutputType( System.getProperty(stringOutputTypeSysPropertyName)); } } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

*

* If not set, null will be returned. *

* * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public void setUnicodeNormalizationIgnored(final Boolean unicodeNormalizationIgnored) { this.unicodeNormalizationIgnoredEnvName = null; this.unicodeNormalizationIgnoredSysPropertyName = null; this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

*

* If not set, null will be returned. *

* * @since 1.4 * * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public void setUnicodeNormalizationIgnored(final String unicodeNormalizationIgnored) { this.unicodeNormalizationIgnoredEnvName = null; this.unicodeNormalizationIgnoredSysPropertyName = null; if (unicodeNormalizationIgnored != null) { this.unicodeNormalizationIgnored = CommonUtils.getStandardBooleanValue(unicodeNormalizationIgnored); } else { this.unicodeNormalizationIgnored = null; } } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.stringOutputTypeEnvName = null; this.stringOutputTypeSysPropertyName = null; this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); } /** *

* Sets the prefix to be added at the beginning of encryption results, and also to * be expected at the beginning of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPrefix()} *

* * @since 1.7 * * @param prefix */ public void setPrefix(final String prefix) { this.prefixEnvName = null; this.prefixSysPropertyName = null; this.prefix = prefix; } /** *

* Sets the suffix to be added at the end of encryption results, and also to * be expected at the end of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSuffix()} *

* * @since 1.7 * * @param suffix */ public void setSuffix(final String suffix) { this.suffixEnvName = null; this.suffixSysPropertyName = null; this.suffix = suffix; } public Boolean isUnicodeNormalizationIgnored() { return this.unicodeNormalizationIgnored; } public String getStringOutputType() { return this.stringOutputType; } public String getPrefix() { return this.prefix; } public String getSuffix() { return this.suffix; } /** * Retrieve the name of the environment variable which value has been * loaded as a value for the "prefix" parameter. * * @since 1.7 * * @return the name of the variable */ public String getPrefixEnvName() { return this.prefixEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the "prefix" parameter. * * @since 1.7 * * @param prefixEnvName the name of the environment * variable */ public void setPrefixEnvName(final String prefixEnvName) { this.prefixEnvName = prefixEnvName; if (prefixEnvName == null) { this.prefix = null; } else { this.prefixSysPropertyName = null; this.prefix = System.getenv(prefixEnvName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as a value for the "prefix" parameter. * * @since 1.7 * * @return the name of the property */ public String getPrefixSysPropertyName() { return this.prefixSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load a value for the "prefix" parameter. * * @since 1.7 * * @param prefixSysPropertyName the name of the property */ public void setPrefixSysPropertyName(final String prefixSysPropertyName) { this.prefixSysPropertyName = prefixSysPropertyName; if (prefixSysPropertyName == null) { this.prefix = null; } else { this.prefixEnvName = null; this.prefix = System.getProperty(prefixSysPropertyName); } } /** * Retrieve the name of the environment variable which value has been * loaded as a value for the "suffix" parameter. * * @since 1.7 * * @return the name of the variable */ public String getSuffixEnvName() { return this.suffixEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the "suffix" parameter. * * @since 1.7 * * @param suffixEnvName the name of the environment * variable */ public void setSuffixEnvName(final String suffixEnvName) { this.suffixEnvName = suffixEnvName; if (suffixEnvName == null) { this.suffix = null; } else { this.suffixSysPropertyName = null; this.suffix = System.getenv(suffixEnvName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as a value for the "suffix" parameter. * * @since 1.7 * * @return the name of the property */ public String getSuffixSysPropertyName() { return this.suffixSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load a value for the "suffix" parameter. * * @since 1.7 * * @param suffixSysPropertyName the name of the property */ public void setSuffixSysPropertyName(final String suffixSysPropertyName) { this.suffixSysPropertyName = suffixSysPropertyName; if (suffixSysPropertyName == null) { this.suffix = null; } else { this.suffixEnvName = null; this.suffix = System.getProperty(suffixSysPropertyName); } } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/SimpleDigesterConfig.java000066400000000000000000000415571360667575700321140ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; import java.security.Provider; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.salt.SaltGenerator; /** *

* Bean implementation for {@link DigesterConfig}. This class allows * the values for the configuration parameters to be set * via "standard" setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

*

* Note that there is not an exact correspondence between setX() * and getX() methods, as sometimes two methods like * setProvider() and setProviderClassName() will affect the * same configuration parameter (getProvider()). This means that * several combinations of setX() methods collide, and * should not be called together (a call to setProviderClassName() * will override any previous call to setProvider()). *

* * @since 1.0 * * @author Daniel Fernández * */ public class SimpleDigesterConfig implements DigesterConfig { private String algorithm = null; private Integer iterations = null; private Integer saltSizeBytes = null; private SaltGenerator saltGenerator = null; private String providerName = null; private Provider provider = null; private Boolean invertPositionOfSaltInMessageBeforeDigesting = null; private Boolean invertPositionOfPlainSaltInEncryptionResults = null; private Boolean useLenientSaltSizeCheck = null; private Integer poolSize = null; /** *

* Creates a new SimpleDigesterConfig instance. *

*/ public SimpleDigesterConfig() { super(); } /** *

* Sets the name of the algorithm. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

*

* Determines the result of: {@link #getAlgorithm()} *

* * @param algorithm the name of the algorithm. */ public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; } /** *

* Sets the number of hashing iterations. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getIterations()} *

* * @param iterations the number of iterations. */ public void setIterations(final Integer iterations) { this.iterations = iterations; } /** *

* Sets the number of hashing iterations. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getIterations()} *

* * @since 1.4 * * @param iterations the number of iterations. */ public void setIterations(final String iterations) { if (iterations != null) { try { this.iterations = new Integer(iterations); } catch (NumberFormatException e) { throw new EncryptionInitializationException(e); } } else { this.iterations = null; } } /** *

* Size in bytes of the salt to be used. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSaltSizeBytes()} *

* * @param saltSizeBytes the size of the salt, in bytes. */ public void setSaltSizeBytes(final Integer saltSizeBytes) { this.saltSizeBytes = saltSizeBytes; } /** *

* Size in bytes of the salt to be used. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSaltSizeBytes()} *

* * @since 1.4 * * @param saltSizeBytes the size of the salt, in bytes. */ public void setSaltSizeBytes(final String saltSizeBytes) { if (saltSizeBytes != null) { try { this.saltSizeBytes = new Integer(saltSizeBytes); } catch (NumberFormatException e) { throw new EncryptionInitializationException(e); } } else { this.saltSizeBytes = null; } } /** *

* Sets the salt generator. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSaltGenerator()} *

* * @since 1.2 * * @param saltGenerator the salt generator. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; } /** *

* Sets the class name of the salt generator. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSaltGenerator()} *

* * @since 1.4 * * @param saltGeneratorClassName the name of the salt generator class. */ public void setSaltGeneratorClassName(final String saltGeneratorClassName) { if (saltGeneratorClassName != null) { try { final Class saltGeneratorClass = Thread.currentThread().getContextClassLoader().loadClass(saltGeneratorClassName); this.saltGenerator = (SaltGenerator) saltGeneratorClass.newInstance(); } catch (Exception e) { throw new EncryptionInitializationException(e); } } else { this.saltGenerator = null; } } /** *

* Sets the name of the security provider to be asked for the digest * algorithm. This provider should be already registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the digester object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProviderName()} *

* * @since 1.3 * * @param providerName the name of the security provider. */ public void setProviderName(final String providerName) { this.providerName = providerName; } /** *

* Sets the security provider to be used for obtaining the digest * algorithm. This method is an alternative to * both {@link #setProviderName(String)} and * {@link #setProviderClassName(String)} and they should not be used * altogether. * The provider specified with {@link #setProvider(Provider)} does not * have to be registered beforehand, and its use will not result in its * being registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the digester object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProvider()} *

* * @since 1.3 * * @param provider the security provider object. */ public void setProvider(final Provider provider) { this.provider = provider; } /** *

* Sets the class name for the security provider to be used for * obtaining the digest algorithm. This method is an alternative to * both {@link #setProviderName(String)} {@link #setProvider(Provider)} * and they should not be used altogether. * The provider specified with {@link #setProviderClassName(String)} does not * have to be registered beforehand, and its use will not result in its * being registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the digester object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProvider()} *

* * @since 1.4 * * @param providerClassName the name of the security provider class. */ public void setProviderClassName(final String providerClassName) { if (providerClassName != null) { try { final Class providerClass = Thread.currentThread().getContextClassLoader().loadClass(providerClassName); this.provider = (Provider) providerClass.newInstance(); } catch (Exception e) { throw new EncryptionInitializationException(e); } } else { this.provider = null; } } /** *

* Whether the salt bytes are to be appended after the * message ones before performing the digest operation on the whole. The * default behaviour is to insert those bytes before the message bytes, but * setting this configuration item to true allows compatibility * with some external systems and specifications (e.g. LDAP {SSHA}). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getInvertPositionOfSaltInMessageBeforeDigesting()} *

* * @since 1.7 * * @param invertPositionOfSaltInMessageBeforeDigesting * whether salt will be appended after the message before applying * the digest operation on the whole, instead of inserted before it * (which is the default). */ public void setInvertPositionOfSaltInMessageBeforeDigesting( final Boolean invertPositionOfSaltInMessageBeforeDigesting) { this.invertPositionOfSaltInMessageBeforeDigesting = invertPositionOfSaltInMessageBeforeDigesting; } /** *

* Whether the plain (not hashed) salt bytes are to * be appended after the digest operation result bytes. The default behaviour is * to insert them before the digest result, but setting this configuration * item to true allows compatibility with some external systems * and specifications (e.g. LDAP {SSHA}). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getInvertPositionOfPlainSaltInEncryptionResults()} *

* * @since 1.7 * * @param invertPositionOfPlainSaltInEncryptionResults * whether plain salt will be appended after the digest operation * result instead of inserted before it (which is the * default). */ public void setInvertPositionOfPlainSaltInEncryptionResults( final Boolean invertPositionOfPlainSaltInEncryptionResults) { this.invertPositionOfPlainSaltInEncryptionResults = invertPositionOfPlainSaltInEncryptionResults; } /** *

* Whether digest matching operations will allow matching * digests with a salt size different to the one configured in the "saltSizeBytes" * property. This is possible because digest algorithms will produce a fixed-size * result, so the remaining bytes from the hashed input will be considered salt. *

*

* This will allow the digester to match digests produced in environments which do not * establish a fixed salt size as standard (for example, SSHA password encryption * in LDAP systems). *

*

* The value of this property will not affect the creation of digests, * which will always have a salt of the size established by the "saltSizeBytes" * property. It will only affect digest matching. *

*

* Setting this property to true is not compatible with {@link SaltGenerator} * implementations which return false for their * {@link SaltGenerator#includePlainSaltInEncryptionResults()} property. *

*

* Also, be aware that some algorithms or algorithm providers might not support * knowing the size of the digests beforehand, which is also incompatible with * a lenient behaviour. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getUseLenientSaltSizeCheck()} *

* * @since 1.7 * * @param useLenientSaltSizeCheck whether the digester will allow matching of * digests with different salt sizes than established or not (default * is false). */ public void setUseLenientSaltSizeCheck(final Boolean useLenientSaltSizeCheck) { this.useLenientSaltSizeCheck = useLenientSaltSizeCheck; } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter will be ignored if used with a non-pooled digester. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPoolSize()} *

* * @since 1.7 * * @param poolSize the size of the pool to be used if this configuration is used with a * pooled digester */ public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter will be ignored if used with a non-pooled digester. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPoolSize()} *

* * @since 1.7 * * @param poolSize the size of the pool to be used if this configuration is used with a * pooled digester */ public void setPoolSize(final String poolSize) { if (poolSize != null) { try { this.poolSize = new Integer(poolSize); } catch (NumberFormatException e) { throw new EncryptionInitializationException(e); } } else { this.poolSize = null; } } public String getAlgorithm() { return this.algorithm; } public Integer getIterations() { return this.iterations; } public Integer getSaltSizeBytes() { return this.saltSizeBytes; } public SaltGenerator getSaltGenerator() { return this.saltGenerator; } public String getProviderName() { return this.providerName; } public Provider getProvider() { return this.provider; } public Boolean getInvertPositionOfSaltInMessageBeforeDigesting() { return this.invertPositionOfSaltInMessageBeforeDigesting; } public Boolean getInvertPositionOfPlainSaltInEncryptionResults() { return this.invertPositionOfPlainSaltInEncryptionResults; } public Boolean getUseLenientSaltSizeCheck() { return this.useLenientSaltSizeCheck; } public Integer getPoolSize() { return this.poolSize; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/SimpleStringDigesterConfig.java000066400000000000000000000157141360667575700332770ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; import org.jasypt.commons.CommonUtils; /** *

* Bean implementation for {@link StringDigesterConfig}. This class allows * the values for the configuration parameters to be set * via "standard" setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class SimpleStringDigesterConfig extends SimpleDigesterConfig implements StringDigesterConfig { private Boolean unicodeNormalizationIgnored = null; private String stringOutputType = null; private String prefix = null; private String suffix = null; /** *

* Creates a new SimpleStringDigesterConfig instance. *

*/ public SimpleStringDigesterConfig() { super(); } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #isUnicodeNormalizationIgnored()} *

* * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public void setUnicodeNormalizationIgnored(final Boolean unicodeNormalizationIgnored) { this.unicodeNormalizationIgnored = unicodeNormalizationIgnored; } /** *

* Sets whether the unicode text normalization step should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #isUnicodeNormalizationIgnored()} *

* * @since 1.4 * * @param unicodeNormalizationIgnored whether the unicode text * normalization step should be ignored or not. */ public void setUnicodeNormalizationIgnored(final String unicodeNormalizationIgnored) { if (unicodeNormalizationIgnored != null) { this.unicodeNormalizationIgnored = CommonUtils.getStandardBooleanValue(unicodeNormalizationIgnored); } else { this.unicodeNormalizationIgnored = null; } } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getStringOutputType()} *

* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); } /** *

* Sets the prefix to be added at the beginning of encryption results, and also to * be expected at the beginning of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPrefix()} *

* * @since 1.7 * * @param prefix */ public void setPrefix(final String prefix) { this.prefix = prefix; } /** *

* Sets the suffix to be added at the end of encryption results, and also to * be expected at the end of plain messages provided for matching operations * (raising an {@link EncryptionOperationNotPossibleException} if not). *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getSuffix()} *

* * @since 1.7 * * @param suffix */ public void setSuffix(final String suffix) { this.suffix = suffix; } public Boolean isUnicodeNormalizationIgnored() { return this.unicodeNormalizationIgnored; } public String getStringOutputType() { return this.stringOutputType; } public String getPrefix() { return this.prefix; } public String getSuffix() { return this.suffix; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/digest/config/StringDigesterConfig.java000066400000000000000000000102661360667575700321220ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest.config; /** *

* Common interface for config classes applicable to * {@link org.jasypt.digest.StandardStringDigester} objects. This interface * extends {@link DigesterConfig} to add config parameters specific to * String digesting. *

*

* This interface lets the user create new StringDigesterConfig * classes which retrieve values for this parameters from different * (and maybe more secure) sources (remote servers, LDAP, other databases...), * and do this transparently for the digester object. *

*

* The config objects passed to a digester will only be queried once * for each configuration parameter, and this will happen * during the initialization of the digester object. *

*

* For a default implementation, see {@link SimpleStringDigesterConfig}. *

* * @since 1.3 * * @author Daniel Fernández * */ public interface StringDigesterConfig extends DigesterConfig { /** *

* This parameter lets the user specify if the Unicode text normalization * step performed during String digest and matching should be ignored. *

*

* The Java Virtual Machine internally handles all Strings as UNICODE. When * digesting or matching digests in jasypt, these Strings are first * normalized to * its NFC form so that digest matching is not affected by the specific * form in which the messages where input. *

*

* It is normally safe (and recommended) to leave this parameter set to * its default FALSE value (and thus DO perform normalization * operations). But in some specific cases in which issues with legacy * software could arise, it might be useful to set this to TRUE. *

*

* For more information on unicode text normalization, see this issue of * Core Java Technologies Tech Tips. *

* * @return whether the unicode text normalization step should be ignored or * not. */ public Boolean isUnicodeNormalizationIgnored(); /** *

* This parameter lets the user specify the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @return The name of the encoding type for String output */ public String getStringOutputType(); /** *

* Adds the returned (plain) prefix at the beginning of generated digests, * and also expects to find it in any plain message provided for matching * operations (raising an {@link EncryptionOperationNotPossibleException} * if not). *

* * @since 1.7 * * @return the prefix to be added to all digests */ public String getPrefix(); /** *

* Adds the returned (plain) suffix at the end of generated digests, * and also expects to find it in any plain message provided for matching * operations (raising an {@link EncryptionOperationNotPossibleException} * if not). *

* * @since 1.7 * * @return the suffix to be added to all digests */ public String getSuffix(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/000077500000000000000000000000001360667575700246355ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/BigDecimalEncryptor.java000066400000000000000000000037251360667575700313750ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption; import java.math.BigDecimal; /** *

* Common interface for all Encryptors which receive a * BigDecimal (arbitrary precision) message and return a BigDecimal result. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface BigDecimalEncryptor { /** * Encrypt the input message * * @param message the message to be encrypted * @return the result of encryption */ public BigDecimal encrypt(BigDecimal message); /** * Decrypt an encrypted message * * @param encryptedMessage the encrypted message to be decrypted * @return the result of decryption */ public BigDecimal decrypt(BigDecimal encryptedMessage); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/BigIntegerEncryptor.java000066400000000000000000000037241360667575700314330ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption; import java.math.BigInteger; /** *

* Common interface for all Encryptors which receive a * BigInteger (arbitrary precision) message and return a BigInteger result. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface BigIntegerEncryptor { /** * Encrypt the input message * * @param message the message to be encrypted * @return the result of encryption */ public BigInteger encrypt(BigInteger message); /** * Decrypt an encrypted message * * @param encryptedMessage the encrypted message to be decrypted * @return the result of decryption */ public BigInteger decrypt(BigInteger encryptedMessage); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/ByteEncryptor.java000066400000000000000000000027521360667575700303170ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption; /** *

* Common interface for all Encryptors which receive a * byte array message and return a byte array result. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface ByteEncryptor { /** * Encrypt the input message * * @param message the message to be encrypted * @return the result of encryption */ public byte[] encrypt(byte[] message); /** * Decrypt an encrypted message * * @param encryptedMessage the encrypted message to be decrypted * @return the result of decryption */ public byte[] decrypt(byte[] encryptedMessage); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/StringEncryptor.java000066400000000000000000000027561360667575700306660ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption; /** *

* Common interface for all Encryptors which receive a * String message and return a String result. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface StringEncryptor { /** * Encrypt the input message * * @param message the message to be encrypted * @return the result of encryption */ public String encrypt(String message); /** * Decrypt an encrypted message * * @param encryptedMessage the encrypted message to be decrypted * @return the result of decryption */ public String decrypt(String encryptedMessage); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/000077500000000000000000000000001360667575700254035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/CleanablePasswordBased.java000066400000000000000000000027171360667575700326050ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all entities which can be set a password in char[] shape, * which can be cleaned once the encryptor is initialized so that no immutable * Strings containing the password are left in memory. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface CleanablePasswordBased extends PasswordBased { /** *

* Sets a password to be used by the encryptor, as a (cleanable) char[]. *

* * @since 1.8 * * @param password the password to be used. */ public void setPasswordCharArray(char[] password); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/NumberUtils.java000066400000000000000000000117041360667575700305220ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; /** * * Utils for processing numbers in encryptors. Intended only for internal * use within jasypt. * * @since 1.2 * * @author Daniel Fernández * */ final class NumberUtils { static byte[] byteArrayFromInt(final int number) { final byte b0 = (byte) (0xff & number); final byte b1 = (byte) (0xff & (number >> 8)); final byte b2 = (byte) (0xff & (number >> 16)); final byte b3 = (byte) (0xff & (number >> 24)); return new byte[] {b3,b2,b1,b0}; } static int intFromByteArray(final byte[] byteArray) { if (byteArray == null || byteArray.length == 0) { throw new IllegalArgumentException( "Cannot convert an empty array into an int"); } int result = (0xff & byteArray[0]); for (int i = 1; i < byteArray.length; i++) { result = (result << 8) | (0xff & byteArray[i]); } return result; } static byte[] processBigIntegerEncryptedByteArray( final byte[] byteArray, final int signum) { // Check size if (byteArray.length > 4) { final int initialSize = byteArray.length; final byte[] encryptedMessageExpectedSizeBytes = new byte[4]; System.arraycopy(byteArray, (initialSize - 4), encryptedMessageExpectedSizeBytes, 0, 4); final byte[] processedByteArray = new byte[initialSize - 4]; System.arraycopy(byteArray, 0, processedByteArray, 0, (initialSize - 4)); final int expectedSize = NumberUtils.intFromByteArray(encryptedMessageExpectedSizeBytes); if (expectedSize < 0 || expectedSize > maxSafeSizeInBytes()) { throw new EncryptionOperationNotPossibleException(); } // If expected and real sizes do not match, we will need to pad // (this happens because BigInteger removes 0x0's and -0x1's in // the leftmost side). if (processedByteArray.length != expectedSize) { // BigInteger can have removed, in the leftmost side: // * 0x0's: for not being significative // * -0x1's: for being translated as the "signum" final int sizeDifference = (expectedSize - processedByteArray.length); final byte[] paddedProcessedByteArray = new byte[expectedSize]; for (int i = 0; i < sizeDifference; i++) { paddedProcessedByteArray[i] = (signum >= 0)? (byte)0x0 : (byte)-0x1; } // Finally, the encrypted message bytes are represented // as they supposedly were when they were encrypted. System.arraycopy(processedByteArray, 0, paddedProcessedByteArray, sizeDifference, processedByteArray.length); return paddedProcessedByteArray; } return processedByteArray; } return (byte[]) byteArray.clone(); } private static long maxSafeSizeInBytes() { // In order to avoid Java heap size exceptions due to // malformations or manipulation of encrypted data, we will // only consider "safe" the allocation of numbers with a size // in bytes less or equal to half the available free memory. // // Available free memory is computed as current free memory // (in the amount of memory currently allocated by the JVM) plus // all the amount of memory that the JVM will be allowed to // allocate in the future (until maxMemory). final long max = Runtime.getRuntime().maxMemory(); final long free = Runtime.getRuntime().freeMemory(); final long total = Runtime.getRuntime().totalMemory(); return ((free + (max - total)) / 2); } private NumberUtils() { super(); } } PBEBigDecimalCleanablePasswordEncryptor.java000066400000000000000000000034551360667575700357250ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all Password Based Encryptors which receive a * BigDecimal message and return a BigDecimal result, and provide means * to set passwords as cleanable char[] objects (instead of * immutable Strings). *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* For a default implementation, see {@link StandardPBEBigDecimalEncryptor}. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface PBEBigDecimalCleanablePasswordEncryptor extends PBEBigDecimalEncryptor, CleanablePasswordBased { // aggregator interface } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PBEBigDecimalEncryptor.java000066400000000000000000000033261360667575700324670ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.jasypt.encryption.BigDecimalEncryptor; /** *

* Common interface for all Password Based Encryptors which receive a * BigDecimal message and return a BigDecimal result. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* For a default implementation, see {@link StandardPBEBigDecimalEncryptor}. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface PBEBigDecimalEncryptor extends BigDecimalEncryptor, PasswordBased { // aggregator interface } PBEBigIntegerCleanablePasswordEncryptor.java000066400000000000000000000034461360667575700357640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all Password Based Encryptors which receive a BigInteger * message and return a BigInteger result, and provide means * to set passwords as cleanable char[] objects (instead of * immutable Strings). *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can result * in an encrypted 16-byte number. This can lead the user into problems if the * encrypted values are to be stored and not enough room has been provided. *

*

* For a default implementation, see {@link StandardPBEBigIntegerEncryptor}. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface PBEBigIntegerCleanablePasswordEncryptor extends PBEBigIntegerEncryptor, CleanablePasswordBased { // aggregator interface } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PBEBigIntegerEncryptor.java000066400000000000000000000033171360667575700325260ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.jasypt.encryption.BigIntegerEncryptor; /** *

* Common interface for all Password Based Encryptors which receive a BigInteger * message and return a BigInteger result. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can result * in an encrypted 16-byte number. This can lead the user into problems if the * encrypted values are to be stored and not enough room has been provided. *

*

* For a default implementation, see {@link StandardPBEBigIntegerEncryptor}. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface PBEBigIntegerEncryptor extends BigIntegerEncryptor, PasswordBased { // aggregator interface } PBEByteCleanablePasswordEncryptor.java000066400000000000000000000025741360667575700346510ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all Password Based Encryptors which receive a * byte array message and return a byte array result, and provide means * to set passwords as cleanable char[] objects (instead of * immutable Strings). *

*

* For a default implementation, see {@link StandardPBEByteEncryptor}. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface PBEByteCleanablePasswordEncryptor extends PBEByteEncryptor, CleanablePasswordBased { // aggregator interface } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PBEByteEncryptor.java000066400000000000000000000024371360667575700314140ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.jasypt.encryption.ByteEncryptor; /** *

* Common interface for all Password Based Encryptors which receive a * byte array message and return a byte array result. *

*

* For a default implementation, see {@link StandardPBEByteEncryptor}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface PBEByteEncryptor extends ByteEncryptor, PasswordBased { // aggregator interface } PBEStringCleanablePasswordEncryptor.java000066400000000000000000000025621360667575700352110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all Password Based Encryptors which receive a * String message and return a String result, and provide means * to set passwords as cleanable char[] objects (instead of * immutable Strings). *

* For a default implementation, see {@link StandardPBEStringEncryptor}. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface PBEStringCleanablePasswordEncryptor extends PBEStringEncryptor, CleanablePasswordBased { // aggregator interface } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PBEStringEncryptor.java000066400000000000000000000024371360667575700317570ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.jasypt.encryption.StringEncryptor; /** *

* Common interface for all Password Based Encryptors which receive a * String message and return a String result. *

*

* For a default implementation, see {@link StandardPBEStringEncryptor}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface PBEStringEncryptor extends StringEncryptor, PasswordBased { // aggregator interface } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PasswordBased.java000066400000000000000000000023361360667575700310130ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; /** *

* Common interface for all entities which can be set a password. *

* * @since 1.3 * * @author Daniel Fernández * */ public interface PasswordBased { /** *

* Sets a password to be used by the encryptor. *

* * @param password the password to be used. */ public void setPassword(String password); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PooledPBEBigDecimalEncryptor.java000066400000000000000000000404571360667575700336400ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigDecimal; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link PBEBigDecimalEncryptor} that in fact contains * an array of {@link StandardPBEBigDecimalEncryptor} objects which are used * to attend encrypt and decrypt requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardPBEBigDecimalEncryptor}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public final class PooledPBEBigDecimalEncryptor implements PBEBigDecimalCleanablePasswordEncryptor { private final StandardPBEBigDecimalEncryptor firstEncryptor; private PBEConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardPBEBigDecimalEncryptor[] pool; private int roundRobin = 0; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardPBEBigDecimalEncryptor. */ public PooledPBEBigDecimalEncryptor() { super(); this.firstEncryptor = new StandardPBEBigDecimalEncryptor(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
  • Output type (base64, hexadecimal) * (only StringPBEConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final PBEConfig config) { this.firstEncryptor.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.firstEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.firstEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { this.firstEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.firstEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.firstEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.firstEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.firstEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.firstEncryptor.setProvider(provider); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = this.firstEncryptor.cloneAndInitializeEncryptor(this.poolSize); this.initialized = true; } } /** *

* Encrypts a message using the specified configuration. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the BigDecimal message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigDecimal encrypt(final BigDecimal message) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].encrypt(message); } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the BigDecimal message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigDecimal decrypt(final BigDecimal encryptedMessage) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PooledPBEBigIntegerEncryptor.java000066400000000000000000000404571360667575700336770ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigInteger; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link PBEBigIntegerEncryptor} that in fact contains * an array of {@link StandardPBEBigIntegerEncryptor} objects which are used * to attend encrypt and decrypt requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardPBEBigIntegerEncryptor}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public final class PooledPBEBigIntegerEncryptor implements PBEBigIntegerCleanablePasswordEncryptor { private final StandardPBEBigIntegerEncryptor firstEncryptor; private PBEConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardPBEBigIntegerEncryptor[] pool; private int roundRobin = 0; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardPBEBigIntegerEncryptor. */ public PooledPBEBigIntegerEncryptor() { super(); this.firstEncryptor = new StandardPBEBigIntegerEncryptor(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
  • Output type (base64, hexadecimal) * (only StringPBEConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final PBEConfig config) { this.firstEncryptor.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.firstEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.firstEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { this.firstEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.firstEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.firstEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.firstEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.firstEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.firstEncryptor.setProvider(provider); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = this.firstEncryptor.cloneAndInitializeEncryptor(this.poolSize); this.initialized = true; } } /** *

* Encrypts a message using the specified configuration. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the BigInteger message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigInteger encrypt(final BigInteger message) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].encrypt(message); } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the BigInteger message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigInteger decrypt(final BigInteger encryptedMessage) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PooledPBEByteEncryptor.java000066400000000000000000000376401360667575700325630ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link PBEByteEncryptor} that in fact contains * an array of {@link StandardPBEByteEncryptor} objects which are used * to attend encrypt and decrypt requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardPBEByteEncryptor}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public final class PooledPBEByteEncryptor implements PBEByteCleanablePasswordEncryptor { private final StandardPBEByteEncryptor firstEncryptor; private PBEConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardPBEByteEncryptor[] pool; private int roundRobin = 0; /* * Flag which indicates whether the encryptor has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardPBEByteEncryptor. */ public PooledPBEByteEncryptor() { super(); this.firstEncryptor = new StandardPBEByteEncryptor(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(PBEConfig config) { this.firstEncryptor.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(String algorithm) { this.firstEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public synchronized void setPassword(String password) { this.firstEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { this.firstEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public synchronized void setKeyObtentionIterations( int keyObtentionIterations) { this.firstEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(SaltGenerator saltGenerator) { this.firstEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public synchronized void setIvGenerator(final IvGenerator ivGenerator) { this.firstEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public synchronized void setProviderName(String providerName) { this.firstEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(Provider provider) { this.firstEncryptor.setProvider(provider); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = this.firstEncryptor.cloneAndInitializeEncryptor(this.poolSize); this.initialized = true; } } /** *

* Encrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the byte array message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] encrypt(final byte[] message) throws EncryptionOperationNotPossibleException { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].encrypt(message); } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the byte array message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] decrypt(final byte[] encryptedMessage) throws EncryptionOperationNotPossibleException { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/PooledPBEStringEncryptor.java000066400000000000000000000410631360667575700331200ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Pooled implementation of {@link PBEStringEncryptor} that in fact contains * an array of {@link StandardPBEStringEncryptor} objects which are used * to attend encrypt and decrypt requests in round-robin. This should * result in higher performance in multiprocessor systems. *

*

* Configuration of this class is equivalent to that of * {@link StandardPBEStringEncryptor}. *

*

* This class is thread-safe. *

* * * @since 1.7 * * @author Daniel Fernández * */ public final class PooledPBEStringEncryptor implements PBEStringCleanablePasswordEncryptor { private final StandardPBEStringEncryptor firstEncryptor; private PBEConfig config = null; private int poolSize = 0; private boolean poolSizeSet = false; private StandardPBEStringEncryptor[] pool; private int roundRobin = 0; /* * Flag which indicates whether the digester has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; /** * Creates a new instance of PooledStandardPBEStringEncryptor. */ public PooledPBEStringEncryptor() { super(); this.firstEncryptor = new StandardPBEStringEncryptor(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
  • Output type (base64, hexadecimal) * (only StringPBEConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final PBEConfig config) { this.firstEncryptor.setConfig(config); this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.firstEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.firstEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { this.firstEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.firstEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.firstEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.firstEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.firstEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.firstEncryptor.setProvider(provider); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @param stringOutputType the string output type. */ public synchronized void setStringOutputType(final String stringOutputType) { this.firstEncryptor.setStringOutputType(stringOutputType); } /** *

* Sets the size of the pool of digesters to be created. *

*

* This parameter is required. *

* * @param poolSize size of the pool */ public synchronized void setPoolSize(final int poolSize) { CommonUtils.validateIsTrue(poolSize > 0, "Pool size be > 0"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.poolSize = poolSize; this.poolSizeSet = true; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null) { final Integer configPoolSize = this.config.getPoolSize(); this.poolSize = ((this.poolSizeSet) || (configPoolSize == null))? this.poolSize : configPoolSize.intValue(); } if (this.poolSize <= 0) { throw new IllegalArgumentException("Pool size must be set and > 0"); } this.pool = this.firstEncryptor.cloneAndInitializeEncryptor(this.poolSize); this.initialized = true; } } /** *

* Encrypts a message using the specified configuration. *

*

* The Strings returned by this method are BASE64-encoded (default) or * HEXADECIMAL ASCII Strings. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the String message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public String encrypt(final String message) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].encrypt(message); } /** *

* Decrypts a message using the specified configuration. *

*

* This method expects to receive a BASE64-encoded (default) * or HEXADECIMAL ASCII String. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the String message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public String decrypt(final String encryptedMessage) { // Check initialization if (!isInitialized()) { initialize(); } int poolPosition; synchronized(this) { poolPosition = this.roundRobin; this.roundRobin = (this.roundRobin + 1) % this.poolSize; } return this.pool[poolPosition].decrypt(encryptedMessage); } } StandardPBEBigDecimalEncryptor.java000066400000000000000000000527361360667575700341020ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigDecimal; import java.math.BigInteger; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link PBEBigDecimalEncryptor} interface. * This class lets the user specify the algorithm (and provider) to be used for * encryption, the password to use, * the number of hashing iterations and the salt generator * that will be applied for obtaining * the encryption key. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, password, key-obtention iterations and salt generator can take * values in any of these ways: *

    *
  • Using its default values (except for password).
  • *
  • Setting a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setAlgorithm(...), * setProvider(...), setProviderName(...), * setPassword(...), setKeyObtentionIterations(...) or * setSaltGenerator(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered (except for password).
  2. *
  3. Then, if a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig(...), the non-null values returned by its * getX() methods override the default values.
  4. *
  5. Finally, if the corresponding setX(...) method has been called * on the encryptor itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to encrypt, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize() is called.
  • *
  • When encrypt(...) or decrypt(...) are called for the * first time, if initialize() has not been called before.
  • *
* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* An encryptor may be used for: *

    *
  • Encrypting messages, by calling the encrypt(...) method.
  • *
  • Decrypting messages, by calling the decrypt(...) method.
  • *
* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

*

* To learn more about the mechanisms involved in encryption, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class StandardPBEBigDecimalEncryptor implements PBEBigDecimalCleanablePasswordEncryptor { // The StandardPBEByteEncryptor that will be internally used. private final StandardPBEByteEncryptor byteEncryptor; /** * Creates a new instance of StandardPBEBigDecimalEncryptor. */ public StandardPBEBigDecimalEncryptor() { super(); this.byteEncryptor = new StandardPBEByteEncryptor(); } /* * Creates a new instance of StandardPBEBigDecimalEncryptor using * the specified byte digester (constructor used for cloning) */ private StandardPBEBigDecimalEncryptor(final StandardPBEByteEncryptor standardPBEByteEncryptor) { super(); this.byteEncryptor = standardPBEByteEncryptor; } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public void setConfig(final PBEConfig config) { this.byteEncryptor.setConfig(config); } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.byteEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.byteEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public void setPasswordCharArray(char[] password) { this.byteEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.byteEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.byteEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.byteEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.byteEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.byteEncryptor.setProvider(provider); } /* * Clone this encryptor 'size' times and initialize it. * This encryptor will be at position 0 itself. * Clones will NOT be initialized. */ synchronized StandardPBEBigDecimalEncryptor[] cloneAndInitializeEncryptor(final int size) { final StandardPBEByteEncryptor[] byteEncryptorClones = this.byteEncryptor.cloneAndInitializeEncryptor(size); final StandardPBEBigDecimalEncryptor[] clones = new StandardPBEBigDecimalEncryptor[size]; clones[0] = this; for (int i = 1; i < size; i++) { clones[i] = new StandardPBEBigDecimalEncryptor(byteEncryptorClones[i]); } return clones; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.byteEncryptor.isInitialized(); } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public void initialize() { this.byteEncryptor.initialize(); } /** *

* Encrypts a message using the specified configuration. *

*

* The resulting * BigDecimal will have the same scale as the original one (although the * total number of bytes will be higher). *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the BigDecimal message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigDecimal encrypt(final BigDecimal message) { if (message == null) { return null; } try { // Get the scale of the decimal number final int scale = message.scale(); // Get the number in binary form (without scale) final BigInteger unscaledMessage = message.unscaledValue(); final byte[] messageBytes = unscaledMessage.toByteArray(); // The StandardPBEByteEncryptor does its job. final byte[] encryptedMessage = this.byteEncryptor.encrypt(messageBytes); // The length of the encrypted message will be stored // with the result itself so that we can correctly rebuild // the complete byte array when decrypting (BigInteger will // ignore all "0x0" bytes in the leftmost side, and also "-0x1" // in the leftmost side will be translated as signum). final byte[] encryptedMessageLengthBytes = NumberUtils.byteArrayFromInt(encryptedMessage.length); // Append the length bytes to the encrypted message final byte[] encryptionResult = CommonUtils.appendArrays(encryptedMessage, encryptedMessageLengthBytes); // Finally, return a new number built from the encrypted bytes return new BigDecimal(new BigInteger(encryptionResult), scale); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If encryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the BigDecimal message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigDecimal decrypt(BigDecimal encryptedMessage) { if (encryptedMessage == null) { return null; } try { // Get the scale int scale = encryptedMessage.scale(); // Get the number (unscaled) in binary form BigInteger unscaledEncryptedMessage = encryptedMessage.unscaledValue(); byte[] encryptedMessageBytes = unscaledEncryptedMessage.toByteArray(); // Process the encrypted byte array (check size, pad if needed...) encryptedMessageBytes = NumberUtils.processBigIntegerEncryptedByteArray( encryptedMessageBytes, encryptedMessage.signum()); // Let the byte encyptor decrypt byte[] message = this.byteEncryptor.decrypt(encryptedMessageBytes); // Finally, return a new number built from the decrypted bytes return new BigDecimal(new BigInteger(message), scale); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If decryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } } StandardPBEBigIntegerEncryptor.java000066400000000000000000000514711360667575700341340ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigInteger; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link PBEBigIntegerEncryptor} interface. * This class lets the user specify the algorithm (and provider) to be used for * encryption, the password to use, * the number of hashing iterations and the salt generator * that will be applied for obtaining * the encryption key. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, password, key-obtention iterations and salt generator can take * values in any of these ways: *

    *
  • Using its default values (except for password).
  • *
  • Setting a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setAlgorithm(...), * setProvider(...), setProviderName(...), * setPassword(...), setKeyObtentionIterations(...) or * setSaltGenerator(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered (except for password).
  2. *
  3. Then, if a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig(...), the non-null values returned by its * getX() methods override the default values.
  4. *
  5. Finally, if the corresponding setX(...) method has been called * on the encryptor itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to encrypt, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize() is called.
  • *
  • When encrypt(...) or decrypt(...) are called for the * first time, if initialize() has not been called before.
  • *
* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* An encryptor may be used for: *

    *
  • Encrypting messages, by calling the encrypt(...) method.
  • *
  • Decrypting messages, by calling the decrypt(...) method.
  • *
* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

*

* To learn more about the mechanisms involved in encryption, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class StandardPBEBigIntegerEncryptor implements PBEBigIntegerCleanablePasswordEncryptor { // The StandardPBEByteEncryptor that will be internally used. private final StandardPBEByteEncryptor byteEncryptor; /** * Creates a new instance of StandardPBEBigIntegerEncryptor. */ public StandardPBEBigIntegerEncryptor() { super(); this.byteEncryptor = new StandardPBEByteEncryptor(); } /* * Creates a new instance of StandardPBEBigIntegerEncryptor using * the specified byte digester (constructor used for cloning) */ private StandardPBEBigIntegerEncryptor(final StandardPBEByteEncryptor standardPBEByteEncryptor) { super(); this.byteEncryptor = standardPBEByteEncryptor; } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public void setConfig(final PBEConfig config) { this.byteEncryptor.setConfig(config); } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.byteEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.byteEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public void setPasswordCharArray(char[] password) { this.byteEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.byteEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.byteEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.byteEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.byteEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.byteEncryptor.setProvider(provider); } /* * Clone this encryptor 'size' times and initialize it. * This encryptor will be at position 0 itself. * Clones will NOT be initialized. */ synchronized StandardPBEBigIntegerEncryptor[] cloneAndInitializeEncryptor(final int size) { final StandardPBEByteEncryptor[] byteEncryptorClones = this.byteEncryptor.cloneAndInitializeEncryptor(size); final StandardPBEBigIntegerEncryptor[] clones = new StandardPBEBigIntegerEncryptor[size]; clones[0] = this; for (int i = 1; i < size; i++) { clones[i] = new StandardPBEBigIntegerEncryptor(byteEncryptorClones[i]); } return clones; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.byteEncryptor.isInitialized(); } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public void initialize() { this.byteEncryptor.initialize(); } /** *

* Encrypts a message using the specified configuration. *

*

* Important: The size of the result of encrypting a number, depending * on the algorithm, may be much bigger (in bytes) than the size of the * encrypted number itself. For example, encrypting a 4-byte integer can * result in an encrypted 16-byte number. This can lead the user into * problems if the encrypted values are to be stored and not enough room * has been provided. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the BigInteger message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigInteger encrypt(BigInteger message) { if (message == null) { return null; } try { // Get the number in binary form final byte[] messageBytes = message.toByteArray(); // The StandardPBEByteEncryptor does its job. final byte[] encryptedMessage = this.byteEncryptor.encrypt(messageBytes); // The length of the encrypted message will be stored // with the result itself so that we can correctly rebuild // the complete byte array when decrypting (BigInteger will // ignore all "0x0" bytes in the leftmost side, and also "-0x1" // in the leftmost side will be translated as signum). final byte[] encryptedMessageLengthBytes = NumberUtils.byteArrayFromInt(encryptedMessage.length); // Append the length bytes to the encrypted message final byte[] encryptionResult = CommonUtils.appendArrays(encryptedMessage, encryptedMessageLengthBytes); // Finally, return a new number built from the encrypted bytes return new BigInteger(encryptionResult); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If encryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the BigInteger message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public BigInteger decrypt(BigInteger encryptedMessage) { if (encryptedMessage == null) { return null; } try { // Get the number in binary form byte[] encryptedMessageBytes = encryptedMessage.toByteArray(); // Process the encrypted byte array (check size, pad if needed...) encryptedMessageBytes = NumberUtils.processBigIntegerEncryptedByteArray( encryptedMessageBytes, encryptedMessage.signum()); // Let the byte encyptor decrypt byte[] message = this.byteEncryptor.decrypt(encryptedMessageBytes); // Finally, return a new number built from the decrypted bytes return new BigInteger(message); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If decryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/StandardPBEByteEncryptor.java000066400000000000000000001334561360667575700331030ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.lang.reflect.Constructor; import java.security.InvalidKeyException; import java.security.Provider; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.PBECleanablePasswordConfig; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.iv.IvGenerator; import org.jasypt.iv.NoIvGenerator; import org.jasypt.normalization.Normalizer; import org.jasypt.salt.FixedSaltGenerator; import org.jasypt.salt.RandomSaltGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link PBEByteEncryptor} interface. * This class lets the user specify the algorithm, provider and * the initialization vector (IV) generator to be used for * encryption, the password to use, * the number of hashing iterations and the salt generator * that will be applied for obtaining the encryption key. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, IV generator, password, key-obtention iterations * and salt generator can take values in any of these ways: *

    *
  • Using its default values (except for password).
  • *
  • Setting a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setAlgorithm(...), * setProvider(...), setProviderName(...), * setIvGenerator(...), * setPassword(...), setKeyObtentionIterations(...) or * setSaltGenerator(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered (except for password).
  2. *
  3. Then, if a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig(...), the non-null values returned by its * getX() methods override the default values.
  4. *
  5. Finally, if the corresponding setX(...) method has been called * on the encryptor itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to encrypt, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize() is called.
  • *
  • When encrypt(...) or decrypt(...) are called for the * first time, if initialize() has not been called before.
  • *
* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* An encryptor may be used for: *

    *
  • Encrypting messages, by calling the encrypt(...) method.
  • *
  • Decrypting messages, by calling the decrypt(...) method.
  • *
* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. * The same applies when a random IV generator is used. *

*

* To learn more about the mechanisms involved in encryption, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.0 * * @author Daniel Fernández * */ public final class StandardPBEByteEncryptor implements PBEByteCleanablePasswordEncryptor { /** * The default algorithm to be used if none specified: PBEWithMD5AndDES. */ public static final String DEFAULT_ALGORITHM = "PBEWithMD5AndDES"; /** * The default number of hashing iterations applied for obtaining the * encryption key from the specified password, set to 1000. */ public static final int DEFAULT_KEY_OBTENTION_ITERATIONS = 1000; /** * The default salt size, only used if the chosen encryption algorithm * is not a block algorithm and thus block size cannot be used as salt size. */ public static final int DEFAULT_SALT_SIZE_BYTES = 8; /** * The default IV size, only used if the chosen encryption algorithm * is not a block algorithm and thus block size cannot be used as IV size. */ public static final int DEFAULT_IV_SIZE_BYTES = 16; // Algorithm (and provider-related info) for Password Based Encoding. private String algorithm = DEFAULT_ALGORITHM; private String providerName = null; private Provider provider = null; // Password to be applied. This will NOT have a default value. If none // is set during configuration, an exception will be thrown. private char[] password = null; // Number of hashing iterations to be applied for obtaining the encryption // key from the specified password. private int keyObtentionIterations = DEFAULT_KEY_OBTENTION_ITERATIONS; // SaltGenerator to be used. Initialization of a salt generator is costly, // and so default value will be applied only in initialize(), if it finally // becomes necessary. private SaltGenerator saltGenerator = null; // Size in bytes of the salt to be used for obtaining the // encryption key. This size will depend on the PBE algorithm being used, // and it will be set to the size of the block for the specific // chosen algorithm (if the algorithm is not a block algorithm, the // default value will be used). private int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES; // IvGenerator to be used. Initialization of a IV generator is costly, // and so default value will be applied only in initialize(), if it finally // becomes necessary. private IvGenerator ivGenerator = null; // Size in bytes of the IV. This size will depend on the PBE algorithm // being used, and it will be set to the size of the block for the specific // chosen algorithm (if the algorithm is not a block algorithm, the // default value will be used). private int ivSizeBytes = DEFAULT_IV_SIZE_BYTES; // Config object set (optionally). private PBEConfig config = null; /* * Set of booleans which indicate whether the config or default values * have to be overriden because of the setX methods having been * called. */ private boolean algorithmSet = false; private boolean passwordSet = false; private boolean iterationsSet = false; private boolean saltGeneratorSet = false; private boolean ivGeneratorSet = false; private boolean providerNameSet = false; private boolean providerSet = false; /* * Flag which indicates whether the encryptor has been initialized or not. * * Once initialized, no further modifications to its configuration will * be allowed. */ private boolean initialized = false; // Encryption key generated. private SecretKey key = null; // Ciphers to be used for encryption and decryption. private Cipher encryptCipher = null; private Cipher decryptCipher = null; // Flag which indicates whether the salt generator being used is a // FixedSaltGenerator implementation (in which case some optimizations can // be applied). private boolean optimizingDueFixedSalt = false; private byte[] fixedSaltInUse = null; /** * Creates a new instance of StandardPBEByteEncryptor. */ public StandardPBEByteEncryptor() { super(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
  • IV generator
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(PBEConfig config) { CommonUtils.validateNotNull(config, "Config cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.config = config; } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public synchronized void setAlgorithm(String algorithm) { CommonUtils.validateNotEmpty(algorithm, "Algorithm cannot be set empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.algorithm = algorithm; this.algorithmSet = true; } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public synchronized void setPassword(String password) { CommonUtils.validateNotEmpty(password, "Password cannot be set empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } if (this.password != null) { // We clean the old password, if there is one. cleanPassword(this.password); } this.password = password.toCharArray(); this.passwordSet = true; } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public synchronized void setPasswordCharArray(char[] password) { CommonUtils.validateNotNull(password, "Password cannot be set null"); CommonUtils.validateIsTrue(password.length > 0, "Password cannot be set empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } if (this.password != null) { // We clean the old password, if there is one. cleanPassword(this.password); } this.password = new char[password.length]; System.arraycopy(password, 0, this.password, 0, password.length); this.passwordSet = true; } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public synchronized void setKeyObtentionIterations( int keyObtentionIterations) { CommonUtils.validateIsTrue(keyObtentionIterations > 0, "Number of iterations for key obtention must be " + "greater than zero"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.keyObtentionIterations = keyObtentionIterations; this.iterationsSet = true; } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public synchronized void setSaltGenerator(SaltGenerator saltGenerator) { CommonUtils.validateNotNull(saltGenerator, "Salt generator cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.saltGenerator = saltGenerator; this.saltGeneratorSet = true; } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public synchronized void setIvGenerator(IvGenerator ivGenerator) { ; if (isInitialized()) { throw new AlreadyInitializedException(); } this.ivGenerator = ivGenerator; this.ivGeneratorSet = true; } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public synchronized void setProviderName(String providerName) { CommonUtils.validateNotNull(providerName, "Provider name cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.providerName = providerName; this.providerNameSet = true; } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public synchronized void setProvider(Provider provider) { CommonUtils.validateNotNull(provider, "Provider cannot be set null"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.provider = provider; this.providerSet = true; } /* * Clone this encryptor 'size' times and initialize it. * This encryptor will be at position 0 itself. * Clones will NOT be initialized. */ synchronized StandardPBEByteEncryptor[] cloneAndInitializeEncryptor(final int size) { if (isInitialized()) { throw new EncryptionInitializationException( "Cannot clone encryptor if it has been already initialized"); } // If there is a config object, this forces the password configured value // (if any) into the this.password property. resolveConfigurationPassword(); final char[] copiedPassword = new char[this.password.length]; System.arraycopy(this.password, 0, copiedPassword, 0, this.password.length); // Initialize the encryptor - note that this will clean the // password (that's why copied it before) initialize(); final StandardPBEByteEncryptor[] clones = new StandardPBEByteEncryptor[size]; clones[0] = this; for (int i = 1; i < size; i++) { final StandardPBEByteEncryptor clone = new StandardPBEByteEncryptor(); clone.setPasswordCharArray(copiedPassword); if (CommonUtils.isNotEmpty(this.algorithm)) { clone.setAlgorithm(this.algorithm); } clone.setKeyObtentionIterations(this.keyObtentionIterations); if (this.provider != null) { clone.setProvider(this.provider); } if (this.providerName != null) { clone.setProviderName(this.providerName); } if (this.saltGenerator != null) { clone.setSaltGenerator(this.saltGenerator); } if (this.ivGenerator != null) { clone.setIvGenerator(this.ivGenerator); } clones[i] = clone; } cleanPassword(copiedPassword); return clones; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.initialized; } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.initialized) { /* * If a PBEConfig object has been set, we need to * consider the values it returns (if, for each value, the * corresponding "setX" method has not been called). */ if (this.config != null) { resolveConfigurationPassword(); final String configAlgorithm = this.config.getAlgorithm(); if (configAlgorithm != null) { CommonUtils.validateNotEmpty(configAlgorithm, "Algorithm cannot be set empty"); } final Integer configKeyObtentionIterations = this.config.getKeyObtentionIterations(); if (configKeyObtentionIterations != null) { CommonUtils.validateIsTrue(configKeyObtentionIterations.intValue() > 0, "Number of iterations for key obtention must be " + "greater than zero"); } final SaltGenerator configSaltGenerator = this.config.getSaltGenerator(); final IvGenerator configIvGenerator = this.config.getIvGenerator(); final String configProviderName = this.config.getProviderName(); if (configProviderName != null) { CommonUtils.validateNotEmpty(configProviderName, "Provider name cannot be empty"); } final Provider configProvider = this.config.getProvider(); this.algorithm = ((this.algorithmSet) || (configAlgorithm == null))? this.algorithm : configAlgorithm; this.keyObtentionIterations = ((this.iterationsSet) || (configKeyObtentionIterations == null))? this.keyObtentionIterations : configKeyObtentionIterations.intValue(); this.saltGenerator = ((this.saltGeneratorSet) || (configSaltGenerator == null))? this.saltGenerator : configSaltGenerator; this.ivGenerator = ((this.ivGeneratorSet) || (configIvGenerator == null))? this.ivGenerator : configIvGenerator; this.providerName = ((this.providerNameSet) || (configProviderName == null))? this.providerName : configProviderName; this.provider = ((this.providerSet) || (configProvider == null))? this.provider : configProvider; } /* * If the encryptor was not set a salt generator in any way, * it is time to apply its default value. */ if (this.saltGenerator == null) { this.saltGenerator = new RandomSaltGenerator(); } /* * Default value is a no-op IV generator to maintain backwards compatibility */ if (this.ivGenerator == null) { this.ivGenerator = new NoIvGenerator(); } try { // Password cannot be null. if (this.password == null) { throw new EncryptionInitializationException( "Password not set for Password Based Encryptor"); } // Normalize password to NFC form final char[] normalizedPassword = Normalizer.normalizeToNfc(this.password); /* * Encryption and decryption Ciphers are created the usual way. */ final PBEKeySpec pbeKeySpec = new PBEKeySpec(normalizedPassword); // We don't need the char[] passwords anymore -> clean! cleanPassword(this.password); cleanPassword(normalizedPassword); if (this.provider != null) { final SecretKeyFactory factory = SecretKeyFactory.getInstance( this.algorithm, this.provider); this.key = factory.generateSecret(pbeKeySpec); this.encryptCipher = Cipher.getInstance(this.algorithm, this.provider); this.decryptCipher = Cipher.getInstance(this.algorithm, this.provider); } else if (this.providerName != null) { final SecretKeyFactory factory = SecretKeyFactory.getInstance( this.algorithm, this.providerName); this.key = factory.generateSecret(pbeKeySpec); this.encryptCipher = Cipher.getInstance(this.algorithm, this.providerName); this.decryptCipher = Cipher.getInstance(this.algorithm, this.providerName); } else { final SecretKeyFactory factory = SecretKeyFactory.getInstance(this.algorithm); this.key = factory.generateSecret(pbeKeySpec); this.encryptCipher = Cipher.getInstance(this.algorithm); this.decryptCipher = Cipher.getInstance(this.algorithm); } } catch (EncryptionInitializationException e) { throw e; } catch (Throwable t) { throw new EncryptionInitializationException(t); } // The salt size and the IV size for the chosen algorithm are set to be equal // to the algorithm's block size (if it is a block algorithm). final int algorithmBlockSize = this.encryptCipher.getBlockSize(); if (algorithmBlockSize > 0) { this.saltSizeBytes = algorithmBlockSize; this.ivSizeBytes = algorithmBlockSize; } this.optimizingDueFixedSalt = (this.saltGenerator instanceof FixedSaltGenerator) && (this.ivGenerator instanceof NoIvGenerator); if (this.optimizingDueFixedSalt) { // Create salt this.fixedSaltInUse = this.saltGenerator.generateSalt(this.saltSizeBytes); /* * Initialize the Cipher objects themselves. Due to the fact that * we will be using a fixed salt, this can be done just once, which * means a better performance at the encrypt/decrypt methods. */ final PBEParameterSpec parameterSpec = new PBEParameterSpec(this.fixedSaltInUse, this.keyObtentionIterations); try { this.encryptCipher.init( Cipher.ENCRYPT_MODE, this.key, parameterSpec); this.decryptCipher.init( Cipher.DECRYPT_MODE, this.key, parameterSpec); } catch (final Exception e) { // If encryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } this.initialized = true; } } private synchronized void resolveConfigurationPassword() { // Double-check to avoid synchronization issues if (!this.initialized) { if (this.config != null && !this.passwordSet) { // Get the configured password. If the config object implements // CleanablePassword, we get password directly as a char array // in order to avoid unnecessary creation of immutable Strings // containing such password. char[] configPassword = null; if (this.config instanceof PBECleanablePasswordConfig) { configPassword = ((PBECleanablePasswordConfig)this.config).getPasswordCharArray(); } else { final String configPwd = this.config.getPassword(); if (configPwd != null) { configPassword = configPwd.toCharArray(); } } if (configPassword != null) { CommonUtils.validateIsTrue(configPassword.length > 0, "Password cannot be set empty"); } if (configPassword != null) { this.password = new char[configPassword.length]; System.arraycopy(configPassword, 0, this.password, 0, configPassword.length); this.passwordSet = true; cleanPassword(configPassword); } // Finally, clean the password at the configuration object if (this.config instanceof PBECleanablePasswordConfig) { ((PBECleanablePasswordConfig)this.config).cleanPassword(); } } } } private static void cleanPassword(final char[] password) { if (password != null) { synchronized (password) { final int pwdLength = password.length; for (int i = 0; i < pwdLength; i++) { password[i] = (char)0; } } } } /** *

* Encrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt and IV for each encryption * operation. Sizes of the salt and IV depends on the algorithm * being used. The salt and the IV, if generated by a random generator, * they are also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. * The same is applied if a random IV generator is used. *

* * @param message the byte array message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] encrypt(final byte[] message) throws EncryptionOperationNotPossibleException { if (message == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } try { final byte[] salt; byte[] iv = null; byte[] encryptedMessage; if (this.optimizingDueFixedSalt) { salt = this.fixedSaltInUse; synchronized (this.encryptCipher) { encryptedMessage = this.encryptCipher.doFinal(message); } } else { // Create salt salt = this.saltGenerator.generateSalt(this.saltSizeBytes); // Create IV iv = this.ivGenerator.generateIv(this.ivSizeBytes); /* * Perform encryption using the Cipher */ final PBEParameterSpec parameterSpec = buildPBEParameterSpec(salt, iv); synchronized (this.encryptCipher) { this.encryptCipher.init( Cipher.ENCRYPT_MODE, this.key, parameterSpec); encryptedMessage = this.encryptCipher.doFinal(message); } } // We build an array containing both the unencrypted IV // and the result of the encryption. This is done only // if the IV generator we are using specifies to do so. if (this.ivGenerator.includePlainIvInEncryptionResults()) { // Insert plain IV before the encryption result encryptedMessage = CommonUtils.appendArrays(iv, encryptedMessage); } // Finally we build an array containing both the unencrypted salt // and the result of the encryption. This is done only // if the salt generator we are using specifies to do so. if (this.saltGenerator.includePlainSaltInEncryptionResults()) { // Insert unhashed salt before the encryption result encryptedMessage = CommonUtils.appendArrays(salt, encryptedMessage); } return encryptedMessage; } catch (final InvalidKeyException e) { // The problem could be not having the unlimited strength policies // installed, so better give a usefull error message. handleInvalidKeyException(e); throw new EncryptionOperationNotPossibleException(); } catch (final Exception e) { // If encryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Decrypts a message using the specified configuration. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

*

* If a random IV generator is used, this decryption operation will * expect to find an unencrypted IV at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the byte array message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public byte[] decrypt(final byte[] encryptedMessage) throws EncryptionOperationNotPossibleException { if (encryptedMessage == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } if (this.saltGenerator.includePlainSaltInEncryptionResults() && this.ivGenerator.includePlainIvInEncryptionResults()) { // Check that the received message is bigger than the salt + IV if (encryptedMessage.length <= this.saltSizeBytes + this.ivSizeBytes) { throw new EncryptionOperationNotPossibleException(); } } else if (this.saltGenerator.includePlainSaltInEncryptionResults()) { // Check that the received message is bigger than the salt if (encryptedMessage.length <= this.saltSizeBytes) { throw new EncryptionOperationNotPossibleException(); } } else if (this.ivGenerator.includePlainIvInEncryptionResults()) { // Check that the received message is bigger than the IV if (encryptedMessage.length <= this.ivSizeBytes) { throw new EncryptionOperationNotPossibleException(); } } try { // If we are using a salt generator which specifies the salt // to be included into the encrypted message itself, get it from // there. If not, the salt is supposed to be fixed and thus the // salt generator can be safely asked for it again. byte[] salt = null; byte[] encryptedMessageKernel = null; if (this.saltGenerator.includePlainSaltInEncryptionResults()) { final int saltStart = 0; final int saltSize = (this.saltSizeBytes < encryptedMessage.length? this.saltSizeBytes : encryptedMessage.length); final int encMesKernelStart = (this.saltSizeBytes < encryptedMessage.length? this.saltSizeBytes : encryptedMessage.length); final int encMesKernelSize = (this.saltSizeBytes < encryptedMessage.length? (encryptedMessage.length - this.saltSizeBytes) : 0); salt = new byte[saltSize]; encryptedMessageKernel = new byte[encMesKernelSize]; System.arraycopy(encryptedMessage, saltStart, salt, 0, saltSize); System.arraycopy(encryptedMessage, encMesKernelStart, encryptedMessageKernel, 0, encMesKernelSize); } else if (!this.optimizingDueFixedSalt){ salt = this.saltGenerator.generateSalt(this.saltSizeBytes); encryptedMessageKernel = encryptedMessage; } else { // this.optimizingDueFixedSalt == true salt = this.fixedSaltInUse; encryptedMessageKernel = encryptedMessage; } byte[] iv = null; byte[] finalEncryptedMessageKernel = null; if (this.ivGenerator.includePlainIvInEncryptionResults()) { final int ivStart = 0; final int ivSize = (this.ivSizeBytes < encryptedMessageKernel.length? this.ivSizeBytes : encryptedMessageKernel.length); final int encMesKernelStart = (this.ivSizeBytes < encryptedMessageKernel.length? this.ivSizeBytes : encryptedMessageKernel.length); final int encMesKernelSize = (this.ivSizeBytes < encryptedMessageKernel.length? (encryptedMessageKernel.length - this.ivSizeBytes) : 0); iv = new byte[ivSize]; finalEncryptedMessageKernel = new byte[encMesKernelSize]; System.arraycopy(encryptedMessageKernel, ivStart, iv, 0, ivSize); System.arraycopy(encryptedMessageKernel, encMesKernelStart, finalEncryptedMessageKernel, 0, encMesKernelSize); } else { iv = ivGenerator.generateIv(ivSizeBytes); finalEncryptedMessageKernel = encryptedMessageKernel; } final byte[] decryptedMessage; if (this.optimizingDueFixedSalt) { /* * Fixed salt is being used, therefore no initialization supposedly needed */ synchronized (this.decryptCipher) { decryptedMessage = this.decryptCipher.doFinal(finalEncryptedMessageKernel); } } else { /* * Perform decryption using the Cipher */ final PBEParameterSpec parameterSpec = buildPBEParameterSpec(salt, iv); synchronized (this.decryptCipher) { this.decryptCipher.init( Cipher.DECRYPT_MODE, this.key, parameterSpec); decryptedMessage = this.decryptCipher.doFinal(finalEncryptedMessageKernel); } } // Return the results return decryptedMessage; } catch (final InvalidKeyException e) { // The problem could be not having the unlimited strength policies // installed, so better give a usefull error message. handleInvalidKeyException(e); throw new EncryptionOperationNotPossibleException(); } catch (final Exception e) { // If decryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } private PBEParameterSpec buildPBEParameterSpec(final byte[] salt, final byte[] iv) { PBEParameterSpec parameterSpec; try { Class[] parameters = {byte[].class, int.class, AlgorithmParameterSpec.class}; Constructor java8Constructor = PBEParameterSpec.class.getConstructor(parameters); Object[] parameterValues = {salt, this.keyObtentionIterations, new IvParameterSpec(iv)}; parameterSpec = java8Constructor.newInstance(parameterValues); } catch (Exception e) { parameterSpec = new PBEParameterSpec(salt, this.keyObtentionIterations); } return parameterSpec; } /* * Method used to provide an useful error message in the case that the * user tried to use a strong PBE algorithm like TripleDES and he/she * has not installed the Unlimited Strength Policy files (the default * message for this is simply "invalid key size", which does not provide * enough clues for the user to know what is really going on). */ private void handleInvalidKeyException(final InvalidKeyException e) { if ((e.getMessage() != null) && ((e.getMessage().toUpperCase().indexOf("KEY SIZE") != -1))) { throw new EncryptionOperationNotPossibleException( "Encryption raised an exception. A possible cause is " + "you are using strong encryption algorithms and " + "you have not installed the Java Cryptography " + "Extension (JCE) Unlimited Strength Jurisdiction " + "Policy Files in this Java Virtual Machine"); } } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/StandardPBEStringEncryptor.java000066400000000000000000000640541360667575700334430ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Provider; import org.jasypt.commons.CommonUtils; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; import org.jasypt.encryption.pbe.config.PBEConfig; import org.jasypt.encryption.pbe.config.StringPBEConfig; import org.jasypt.exceptions.AlreadyInitializedException; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Standard implementation of the {@link PBEStringEncryptor} interface. * This class lets the user specify the algorithm (and provider) to be used for * encryption, the password to use, * the number of hashing iterations and the salt generator * that will be applied for obtaining * the encryption key. *

*

* This class avoids byte-conversion problems related to the fact of * different platforms having different default charsets, and returns * encryption results in the form of BASE64-encoded or HEXADECIMAL * ASCII Strings. *

*

* This class is thread-safe. *

*

*
Configuration *

*

* The algorithm, provider, password, key-obtention iterations and salt generator can take * values in any of these ways: *

    *
  • Using its default values (except for password).
  • *
  • Setting a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object which provides new * configuration values.
  • *
  • Calling the corresponding setX(...) methods.
  • *
* And the actual values to be used for initialization will be established * by applying the following priorities: *
    *
  1. First, the default values are considered (except for password).
  2. *
  3. Then, if a {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig(...), the non-null values returned by its * getX() methods override the default values.
  4. *
  5. Finally, if the corresponding setX(...) method has been called * on the encryptor itself for any of the configuration parameters, the * values set by these calls override all of the above.
  6. *
*

* *

*
Initialization *

*

* Before it is ready to encrypt, an object of this class has to be * initialized. Initialization happens: *

    *
  • When initialize() is called.
  • *
  • When encrypt(...) or decrypt(...) are called for the * first time, if initialize() has not been called before.
  • *
* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* *

*
Usage *

*

* An encryptor may be used for: *

    *
  • Encrypting messages, by calling the encrypt(...) method.
  • *
  • Decrypting messages, by calling the decrypt(...) method.
  • *
* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

*

* To learn more about the mechanisms involved in encryption, read * PKCS #5: Password-Based Cryptography Standard. *

* * @since 1.0 * * @author Daniel Fernández * */ public final class StandardPBEStringEncryptor implements PBEStringCleanablePasswordEncryptor { /** *

* Charset to be used to obtain "encryptable" byte arrays from input * Strings. Set to UTF-8. *

*

* This charset has to be fixed to some value so that we avoid problems * with different platforms having different "default" charsets. *

*

* It is set to UTF-8 because it covers the whole spectrum of * characters representable in Java (which internally uses UTF-16), and * avoids the size penalty of UTF-16 (which will always use two bytes for * representing each character, even if it is an ASCII one). *

*

* Setting it to UTF-8 does not mean that Strings that originally come, * for example, from an ISO-8859-1 input, won't be correctly encoded, as we * only need to use the same charset both when encoding and decoding. That * way the same String will be reconstructed independently of the original * encoding (for encrypting, we only need "a byte representation" of the * string, not "a readable byte representation"). *

*/ private static final String MESSAGE_CHARSET = "UTF-8"; /** *

* Charset to be used for encoding the encryption results. * Set to US-ASCII. *

*

* The result of encrypting some bytes can be any other bytes, and so * the result of encrypting, for example, some LATIN-1 valid String bytes, * can be bytes that may not conform a "valid" LATIN-1 String. *

*

* Because of this, encryption results are always encoded in BASE64 * (default) or HEXADECIMAL after being created, and this ensures * that the results will make perfectly representable, safe ASCII Strings. * Because of this, the charset used to convert the encrypted bytes to the * returned String is set to US-ASCII. *

*/ private static final String ENCRYPTED_MESSAGE_CHARSET = "US-ASCII"; /** *

* Default type of String output. Set to BASE64. *

*/ public static final String DEFAULT_STRING_OUTPUT_TYPE = CommonUtils.STRING_OUTPUT_TYPE_BASE64; // If the config object set is a StringPBEConfig, it must be referenced private StringPBEConfig stringPBEConfig = null; // This variable holds the type of String output which will be done, // and also a boolean variable for faster comparison private String stringOutputType = DEFAULT_STRING_OUTPUT_TYPE; private boolean stringOutputTypeBase64 = true; /* * Set of booleans which indicate whether the config or default values * have to be overriden because of the setX methods having been * called. */ private boolean stringOutputTypeSet = false; // The StandardPBEByteEncryptor that will be internally used. private final StandardPBEByteEncryptor byteEncryptor; // BASE64 encoder which will make sure the returned results are // valid US-ASCII strings. // The Base64 encoder is THREAD-SAFE private final Base64 base64; /** * Creates a new instance of StandardPBEStringEncryptor. */ public StandardPBEStringEncryptor() { super(); this.byteEncryptor = new StandardPBEByteEncryptor(); this.base64 = new Base64(); } /* * Creates a new instance of StandardPBEStringEncryptor using * the specified byte encryptor (constructor used for cloning) */ private StandardPBEStringEncryptor(final StandardPBEByteEncryptor standardPBEByteEncryptor) { super(); this.byteEncryptor = standardPBEByteEncryptor; this.base64 = new Base64(); } /** *

* Sets a {@link org.jasypt.encryption.pbe.config.PBEConfig} object * for the encryptor. If this config * object is set, it will be asked values for: *

* *
    *
  • Algorithm
  • *
  • Security Provider (or provider name)
  • *
  • Password
  • *
  • Hashing iterations for obtaining the encryption key
  • *
  • Salt generator
  • *
  • Output type (base64, hexadecimal) * (only StringPBEConfig)
  • *
* *

* The non-null values it returns will override the default ones, * and will be overriden by any values specified with a setX * method. *

* * @param config the PBEConfig object to be used as the * source for configuration parameters. */ public synchronized void setConfig(final PBEConfig config) { this.byteEncryptor.setConfig(config); if ((config != null) && (config instanceof StringPBEConfig)) { this.stringPBEConfig = (StringPBEConfig) config; } } /** *

* Sets the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

*

* This algorithm has to be supported by your JCE provider (if you specify * one, or the default JVM provider if you don't) and, if it is supported, * you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

* * @param algorithm the name of the algorithm to be used. */ public void setAlgorithm(final String algorithm) { this.byteEncryptor.setAlgorithm(algorithm); } /** *

* Sets the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @param password the password to be used. */ public void setPassword(final String password) { this.byteEncryptor.setPassword(password); } /** *

* Sets the password to be used, as a char[]. *

*

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored as encryptor configuration. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @since 1.8 * * @param password the password to be used. */ public void setPasswordCharArray(char[] password) { this.byteEncryptor.setPasswordCharArray(password); } /** *

* Set the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @param keyObtentionIterations the number of iterations */ public void setKeyObtentionIterations(final int keyObtentionIterations) { this.byteEncryptor.setKeyObtentionIterations(keyObtentionIterations); } /** *

* Sets the salt generator to be used. If no salt generator is specified, * an instance of {@link org.jasypt.salt.RandomSaltGenerator} will be used. *

* * @param saltGenerator the salt generator to be used. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.byteEncryptor.setSaltGenerator(saltGenerator); } /** *

* Sets the IV generator to be used. If no IV generator is specified, * an instance of {@link org.jasypt.iv.NoIvGenerator} will be used. *

* * @param ivGenerator the IV generator to be used. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.byteEncryptor.setIvGenerator(ivGenerator); } /** *

* Sets the name of the security provider to be asked for the * encryption algorithm. This security provider has to be registered * beforehand at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the encryption algorithm. */ public void setProviderName(final String providerName) { this.byteEncryptor.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the encryption algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * its being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm */ public void setProvider(final Provider provider) { this.byteEncryptor.setProvider(provider); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* @since 1.3 * * @param stringOutputType the string output type. */ public synchronized void setStringOutputType(final String stringOutputType) { CommonUtils.validateNotEmpty(stringOutputType, "String output type cannot be set empty"); if (isInitialized()) { throw new AlreadyInitializedException(); } this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); this.stringOutputTypeSet = true; } /* * Clone this encryptor 'size' times and initialize it. * This encryptor will be at position 0 itself. * Clones will NOT be initialized. */ synchronized StandardPBEStringEncryptor[] cloneAndInitializeEncryptor(final int size) { final StandardPBEByteEncryptor[] byteEncryptorClones = this.byteEncryptor.cloneAndInitializeEncryptor(size); initializeSpecifics(); final StandardPBEStringEncryptor[] clones = new StandardPBEStringEncryptor[size]; clones[0] = this; for (int i = 1; i < size; i++) { clones[i] = new StandardPBEStringEncryptor(byteEncryptorClones[i]); if (CommonUtils.isNotEmpty(this.stringOutputType)) { clones[i].setStringOutputType(this.stringOutputType); } } return clones; } /** *

* Returns true if the encryptor has already been initialized, false if * not.
* Initialization happens: *

*
    *
  • When initialize is called.
  • *
  • When encrypt or decrypt are called for the * first time, if initialize has not been called before.
  • *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @return true if the encryptor has already been initialized, false if * not. */ public boolean isInitialized() { return this.byteEncryptor.isInitialized(); } /** *

* Initialize the encryptor. *

*

* This operation will consist in determining the actual configuration * values to be used, and then initializing the encryptor with them. *
* These values are decided by applying the following priorities: *

*
    *
  1. First, the default values are considered (except for password). *
  2. *
  3. Then, if a * {@link org.jasypt.encryption.pbe.config.PBEConfig} * object has been set with * setConfig, the non-null values returned by its * getX methods override the default values.
  4. *
  5. Finally, if the corresponding setX method has been called * on the encryptor itself for any of the configuration parameters, * the values set by these calls override all of the above.
  6. *
*

* Once an encryptor has been initialized, trying to * change its configuration will * result in an AlreadyInitializedException being thrown. *

* * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public synchronized void initialize() { // Double-check to avoid synchronization issues if (!this.isInitialized()) { initializeSpecifics(); this.byteEncryptor.initialize(); } } private void initializeSpecifics() { /* * If a StringPBEConfig object has been set, we need to * consider the values it returns (if, for each value, the * corresponding "setX" method has not been called). */ if (this.stringPBEConfig != null) { final String configStringOutputType = this.stringPBEConfig.getStringOutputType(); this.stringOutputType = ((this.stringOutputTypeSet) || (configStringOutputType == null))? this.stringOutputType : configStringOutputType; } this.stringOutputTypeBase64 = (CommonUtils.STRING_OUTPUT_TYPE_BASE64. equalsIgnoreCase(this.stringOutputType)); } /** *

* Encrypts a message using the specified configuration. *

*

* The Strings returned by this method are BASE64-encoded (default) or * HEXADECIMAL ASCII Strings. *

*

* The mechanisms applied to perform the encryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* This encryptor uses a salt for each encryption * operation. The size of the salt depends on the algorithm * being used. This salt is used * for creating the encryption key and, if generated by a random generator, * it is also appended unencrypted at the beginning * of the results so that a decryption operation can be performed. *

*

* If a random salt generator is used, two encryption results for * the same message will always be different * (except in the case of random salt coincidence). This may enforce * security by difficulting brute force attacks on sets of data at a time * and forcing attackers to perform a brute force attack on each separate * piece of encrypted data. *

* * @param message the String message to be encrypted * @return the result of encryption * @throws EncryptionOperationNotPossibleException if the encryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public String encrypt(final String message) { if (message == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } try { // The input String is converted into bytes using MESSAGE_CHARSET // as a fixed charset to avoid problems with different platforms // having different default charsets (see MESSAGE_CHARSET doc). final byte[] messageBytes = message.getBytes(MESSAGE_CHARSET); // The StandardPBEByteEncryptor does its job. byte[] encryptedMessage = this.byteEncryptor.encrypt(messageBytes); // We encode the result in BASE64 or HEXADECIMAL so that we obtain // the safest result String possible. String result = null; if (this.stringOutputTypeBase64) { encryptedMessage = this.base64.encode(encryptedMessage); result = new String(encryptedMessage,ENCRYPTED_MESSAGE_CHARSET); } else { result = CommonUtils.toHexadecimal(encryptedMessage); } return result; } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If encryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } /** *

* Decrypts a message using the specified configuration. *

*

* This method expects to receive a BASE64-encoded (default) * or HEXADECIMAL ASCII String. *

*

* The mechanisms applied to perform the decryption operation are described * in PKCS #5: Password-Based Cryptography Standard. *

*

* If a random salt generator is used, this decryption operation will * expect to find an unencrypted salt at the * beginning of the encrypted input, so that the decryption operation can be * correctly performed (there is no other way of knowing it). *

* * @param encryptedMessage the String message to be decrypted * @return the result of decryption * @throws EncryptionOperationNotPossibleException if the decryption * operation fails, ommitting any further information about the * cause for security reasons. * @throws EncryptionInitializationException if initialization could not * be correctly done (for example, no password has been set). */ public String decrypt(final String encryptedMessage) { if (encryptedMessage == null) { return null; } // Check initialization if (!isInitialized()) { initialize(); } try { byte[] encryptedMessageBytes = null; // Decode input to bytes depending on whether it is a // BASE64-encoded or hexadecimal String if (this.stringOutputTypeBase64) { encryptedMessageBytes = encryptedMessage.getBytes(ENCRYPTED_MESSAGE_CHARSET); encryptedMessageBytes = this.base64.decode(encryptedMessageBytes); } else { encryptedMessageBytes = CommonUtils.fromHexadecimal(encryptedMessage); } // Let the byte encyptor decrypt final byte[] message = this.byteEncryptor.decrypt(encryptedMessageBytes); // Return the resulting decrypted String, using MESSAGE_CHARSET // as charset to maintain between encryption and decyption // processes. return new String(message, MESSAGE_CHARSET); } catch (EncryptionInitializationException e) { throw e; } catch (EncryptionOperationNotPossibleException e) { throw e; } catch (Exception e) { // If decryption fails, it is more secure not to return any // information about the cause in nested exceptions. Simply fail. throw new EncryptionOperationNotPossibleException(); } } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/000077500000000000000000000000001360667575700266505ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/EnvironmentPBEConfig.java000066400000000000000000000552121360667575700335010ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import java.security.Provider; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Implementation for {@link PBEConfig} which can retrieve configuration * values from environment variables or system properties. *

*

* The name of the environment variable or system property (JVM property) to * query for each parameter can be set with its corresponding * setXEnvName or setXSysProperty method. *

*

* As this class extends {@link SimplePBEConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its value is not configured * in any way, a null value will be returned by the * corresponding getX method. *

* * @since 1.1 * * @author Daniel Fernández * */ public class EnvironmentPBEConfig extends SimplePBEConfig { private String algorithmEnvName = null; private String keyObtentionIterationsEnvName = null; private String passwordEnvName = null; private String saltGeneratorClassNameEnvName = null; private String ivGeneratorClassNameEnvName = null; private String providerNameEnvName = null; private String providerClassNameEnvName = null; private String poolSizeEnvName = null; private String algorithmSysPropertyName = null; private String keyObtentionIterationsSysPropertyName = null; private String passwordSysPropertyName = null; private String saltGeneratorClassNameSysPropertyName = null; private String ivGeneratorClassNameSysPropertyName = null; private String providerNameSysPropertyName = null; private String providerClassNameSysPropertyName = null; private String poolSizeSysPropertyName = null; /** *

* Creates a new EnvironmentPBEConfig instance. *

*/ public EnvironmentPBEConfig() { super(); } /** * Retrieve the name of the environment variable which value has been * loaded as the algorithm. * * @return the name of the variable */ public String getAlgorithmEnvName() { return this.algorithmEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the algorithm. * * @param algorithmEnvName the name of the environment variable */ public void setAlgorithmEnvName(final String algorithmEnvName) { this.algorithmEnvName = algorithmEnvName; if (algorithmEnvName == null) { super.setAlgorithm(null); } else { this.algorithmSysPropertyName = null; super.setAlgorithm(System.getenv(algorithmEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the algorithm. * * @return the name of the property */ public String getAlgorithmSysPropertyName() { return this.algorithmSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the algorithm. * * @param algorithmSysPropertyName the name of the property */ public void setAlgorithmSysPropertyName(final String algorithmSysPropertyName) { this.algorithmSysPropertyName = algorithmSysPropertyName; if (algorithmSysPropertyName == null) { super.setAlgorithm(null); } else { this.algorithmEnvName = null; super.setAlgorithm(System.getProperty(algorithmSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the key obtention iteration count. * * @return the name of the variable */ public String getKeyObtentionIterationsEnvName() { return this.keyObtentionIterationsEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the key obtention iteration count. * * @param keyObtentionIterationsEnvName the name of the environment variable */ public void setKeyObtentionIterationsEnvName(final String keyObtentionIterationsEnvName) { this.keyObtentionIterationsEnvName = keyObtentionIterationsEnvName; if (keyObtentionIterationsEnvName == null) { super.setKeyObtentionIterations((Integer)null); } else { this.keyObtentionIterationsSysPropertyName = null; super.setKeyObtentionIterations( System.getenv(keyObtentionIterationsEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the key obtention iteration count. * * @return the name of the property */ public String getKeyObtentionIterationsSysPropertyName() { return this.keyObtentionIterationsSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the key obtention iteration count. * * @param keyObtentionIterationsSysPropertyName the name of the property */ public void setKeyObtentionIterationsSysPropertyName(final String keyObtentionIterationsSysPropertyName) { this.keyObtentionIterationsSysPropertyName = keyObtentionIterationsSysPropertyName; if (keyObtentionIterationsSysPropertyName == null) { super.setKeyObtentionIterations((Integer)null); } else { this.keyObtentionIterationsEnvName = null; super.setKeyObtentionIterations( System.getProperty(keyObtentionIterationsSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the password. * * @return the name of the variable */ public String getPasswordEnvName() { return this.passwordEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the password. * * @param passwordEnvName the name of the environment variable */ public void setPasswordEnvName(final String passwordEnvName) { this.passwordEnvName = passwordEnvName; if (passwordEnvName == null) { super.setPassword(null); } else { this.passwordSysPropertyName = null; super.setPassword(System.getenv(passwordEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the password. * * @return the name of the property */ public String getPasswordSysPropertyName() { return this.passwordSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the password. * * @param passwordSysPropertyName the name of the property */ public void setPasswordSysPropertyName(final String passwordSysPropertyName) { this.passwordSysPropertyName = passwordSysPropertyName; if (passwordSysPropertyName == null) { super.setPassword(null); } else { this.passwordEnvName = null; super.setPassword(System.getProperty(passwordSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the salt generator class name. * * @since 1.3 * * @return the name of the variable */ public String getSaltGeneratorClassNameEnvName() { return this.saltGeneratorClassNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the salt generator class name. *

*

* The salt generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.3 * * @param saltGeneratorClassNameEnvName the name of the environment variable */ public void setSaltGeneratorClassNameEnvName(final String saltGeneratorClassNameEnvName) { this.saltGeneratorClassNameEnvName = saltGeneratorClassNameEnvName; if (saltGeneratorClassNameEnvName == null) { super.setSaltGenerator(null); } else { this.saltGeneratorClassNameSysPropertyName = null; final String saltGeneratorClassName = System.getenv(saltGeneratorClassNameEnvName); super.setSaltGeneratorClassName(saltGeneratorClassName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the salt generator class name. * * @since 1.3 * * @return the name of the property */ public String getSaltGeneratorClassNameSysPropertyName() { return this.saltGeneratorClassNameSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the salt generator class name. *

*

* The salt generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.3 * * @param saltGeneratorClassNameSysPropertyName the name of the property */ public void setSaltGeneratorClassNameSysPropertyName(final String saltGeneratorClassNameSysPropertyName) { this.saltGeneratorClassNameSysPropertyName = saltGeneratorClassNameSysPropertyName; if (saltGeneratorClassNameSysPropertyName == null) { super.setSaltGenerator(null); } else { this.saltGeneratorClassNameEnvName = null; final String saltGeneratorClassName = System.getProperty(saltGeneratorClassNameSysPropertyName); super.setSaltGeneratorClassName(saltGeneratorClassName); } } /** * Retrieve the name of the environment variable which value has been * loaded as the IV generator class name. * * @since 1.9.3 * * @return the name of the variable */ public String getIvGeneratorClassNameEnvName() { return this.ivGeneratorClassNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the IV generator class name. *

*

* The IV generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.9.3 * * @param ivGeneratorClassNameEnvName the name of the environment variable */ public void setIvGeneratorClassNameEnvName(final String ivGeneratorClassNameEnvName) { this.ivGeneratorClassNameEnvName = ivGeneratorClassNameEnvName; if (ivGeneratorClassNameEnvName == null) { super.setIvGenerator(null); } else { this.ivGeneratorClassNameSysPropertyName = null; final String ivGeneratorClassName = System.getenv(ivGeneratorClassNameEnvName); super.setIvGeneratorClassName(ivGeneratorClassName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the IV generator class name. * * @since 1.9.3 * * @return the name of the property */ public String getIvGeneratorClassNameSysPropertyName() { return this.ivGeneratorClassNameSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the IV generator class name. *

*

* The IV generator class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.9.3 * * @param ivGeneratorClassNameSysPropertyName the name of the property */ public void setIvGeneratorClassNameSysPropertyName(final String ivGeneratorClassNameSysPropertyName) { this.ivGeneratorClassNameSysPropertyName = ivGeneratorClassNameSysPropertyName; if (ivGeneratorClassNameSysPropertyName == null) { super.setIvGenerator(null); } else { this.ivGeneratorClassNameEnvName = null; final String ivGeneratorClassName = System.getProperty(ivGeneratorClassNameSysPropertyName); super.setIvGeneratorClassName(ivGeneratorClassName); } } /** * Retrieve the name of the environment variable which value has been * loaded as the provider name. * * @since 1.3 * * @return the name of the variable */ public String getProviderNameEnvName() { return this.providerNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the provider name. *

* * @since 1.3 * * @param providerNameEnvName the name of the environment variable */ public void setProviderNameEnvName(final String providerNameEnvName) { this.providerNameEnvName = providerNameEnvName; if (providerNameEnvName == null) { super.setProviderName(null); } else { this.providerNameSysPropertyName = null; super.setProviderName(System.getenv(providerNameEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the provider name. * * @since 1.3 * * @return the name of the property */ public String getProviderNameSysPropertyName() { return this.providerNameSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the provider name. * * @since 1.3 * * @param providerNameSysPropertyName the name of the property */ public void setProviderNameSysPropertyName(final String providerNameSysPropertyName) { this.providerNameSysPropertyName = providerNameSysPropertyName; if (providerNameSysPropertyName == null) { super.setProviderName(null); } else { this.providerNameEnvName = null; super.setProviderName( System.getProperty(providerNameSysPropertyName)); } } /** * Retrieve the name of the environment variable which value has been * loaded as the provider class name. * * @since 1.3 * * @return the name of the variable */ public String getProviderClassNameEnvName() { return this.providerClassNameEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the provider class name. *

*

* The provider class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.3 * * @param providerClassNameEnvName the name of the environment variable */ public void setProviderClassNameEnvName(final String providerClassNameEnvName) { this.providerClassNameEnvName = providerClassNameEnvName; if (providerClassNameEnvName == null) { super.setProvider(null); } else { this.providerClassNameSysPropertyName = null; final String providerClassName = System.getenv(providerClassNameEnvName); super.setProviderClassName(providerClassName); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the provider class name. * * @since 1.3 * * @return the name of the property */ public String getProviderClassNameSysPropertyName() { return this.providerClassNameSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the provider class name. *

*

* The provider class name which is set here must have a no-argument * constructor, so that it can be instantiated and passed to the encryptor. *

* * @since 1.3 * * @param providerClassNameSysPropertyName the name of the property */ public void setProviderClassNameSysPropertyName(final String providerClassNameSysPropertyName) { this.providerClassNameSysPropertyName = providerClassNameSysPropertyName; if (providerClassNameSysPropertyName == null) { super.setProvider(null); } else { this.providerClassNameEnvName = null; final String providerClassName = System.getProperty(providerClassNameSysPropertyName); super.setProviderClassName(providerClassName); } } /** * Retrieve the name of the environment variable which value has been * loaded as the value for the poolSize * property. * * @since 1.7 * * @return the name of the variable */ public String getPoolSizeEnvName() { return this.poolSizeEnvName; } /** *

* Set the config object to use the specified environment variable to * load the value for the poolSize * property. *

* * @since 1.7 * * @param poolSizeEnvName the name of the environment variable */ public void setPoolSizeEnvName(final String poolSizeEnvName) { this.poolSizeEnvName = poolSizeEnvName; if (poolSizeEnvName == null) { super.setPoolSize((String)null); } else { this.poolSizeSysPropertyName = null; super.setPoolSize(System.getenv(poolSizeEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the value for the poolSize * property. * * @since 1.7 * * @return the name of the property */ public String getPoolSizeSysPropertyName() { return this.poolSizeSysPropertyName; } /** *

* Set the config object to use the specified JVM system property to * load the value for the useLenientSaltSizeCheck * property. *

* * @since 1.7 * * @param poolSizeSysPropertyName the name of the property */ public void setPoolSizeSysPropertyName(final String poolSizeSysPropertyName) { this.poolSizeSysPropertyName = poolSizeSysPropertyName; if (poolSizeSysPropertyName == null) { super.setPoolSize((String)null); } else { this.poolSizeEnvName = null; super.setPoolSize(System.getProperty(poolSizeSysPropertyName)); } } public void setAlgorithm(final String algorithm) { this.algorithmEnvName = null; this.algorithmSysPropertyName = null; super.setAlgorithm(algorithm); } public void setKeyObtentionIterations(final Integer keyObtentionIterations) { this.keyObtentionIterationsEnvName = null; this.keyObtentionIterationsSysPropertyName = null; super.setKeyObtentionIterations(keyObtentionIterations); } public void setKeyObtentionIterations(final String keyObtentionIterations) { this.keyObtentionIterationsEnvName = null; this.keyObtentionIterationsSysPropertyName = null; super.setKeyObtentionIterations(keyObtentionIterations); } public void setPassword(final String password) { this.passwordEnvName = null; this.passwordSysPropertyName = null; super.setPassword(password); } public void setPasswordCharArray(final char[] password) { this.passwordEnvName = null; this.passwordSysPropertyName = null; super.setPasswordCharArray(password); } public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGeneratorClassNameEnvName = null; this.saltGeneratorClassNameSysPropertyName = null; super.setSaltGenerator(saltGenerator); } public void setSaltGeneratorClassName(final String saltGeneratorClassName) { this.saltGeneratorClassNameEnvName = null; this.saltGeneratorClassNameSysPropertyName = null; super.setSaltGeneratorClassName(saltGeneratorClassName); } public void setIvGenerator(final IvGenerator ivGenerator) { this.ivGeneratorClassNameEnvName = null; this.ivGeneratorClassNameSysPropertyName = null; super.setIvGenerator(ivGenerator); } public void setIvGeneratorClassName(final String ivGeneratorClassName) { this.ivGeneratorClassNameEnvName = null; this.ivGeneratorClassNameSysPropertyName = null; super.setIvGeneratorClassName(ivGeneratorClassName); } public void setProviderName(final String providerName) { this.providerNameEnvName = null; this.providerNameSysPropertyName = null; super.setProviderName(providerName); } public void setProvider(final Provider provider) { this.providerClassNameEnvName = null; this.providerClassNameSysPropertyName = null; super.setProvider(provider); } public void setProviderClassName(final String providerClassName) { this.providerClassNameEnvName = null; this.providerClassNameSysPropertyName = null; super.setProviderClassName(providerClassName); } public void setPoolSize(final Integer poolSize) { this.poolSizeEnvName = null; this.poolSizeSysPropertyName = null; super.setPoolSize(poolSize); } public void setPoolSize(final String poolSize) { this.poolSizeEnvName = null; this.poolSizeSysPropertyName = null; super.setPoolSize(poolSize); } } EnvironmentStringPBEConfig.java000066400000000000000000000115461360667575700346130ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import org.jasypt.commons.CommonUtils; /** *

* Implementation for {@link StringPBEConfig} which can retrieve configuration * values from environment variables or system properties. *

*

* The name of the environment variable or system property (JVM property) to * query for each parameter can be set with its corresponding * setXEnvName or setXSysProperty method. *

*

* As this class extends {@link SimplePBEConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its value is not configured * in any way, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class EnvironmentStringPBEConfig extends EnvironmentPBEConfig implements StringPBEConfig { private String stringOutputType = null; private String stringOutputTypeEnvName = null; private String stringOutputTypeSysPropertyName = null; /** *

* Creates a new EnvironmentStringPBEConfig instance. *

*/ public EnvironmentStringPBEConfig() { super(); } /** * Retrieve the name of the environment variable which value has been * loaded as the String output type. * * @return the name of the variable */ public String getStringOutputTypeEnvName() { return this.stringOutputTypeEnvName; } /** * Set the config object to use the specified environment variable to * load the value for the String output type. * * @param stringOutputTypeEnvName the name of the environment variable */ public void setStringOutputTypeEnvName(final String stringOutputTypeEnvName) { this.stringOutputTypeEnvName = stringOutputTypeEnvName; if (stringOutputTypeEnvName == null) { this.stringOutputType = null; } else { this.stringOutputTypeSysPropertyName = null; this.stringOutputType = CommonUtils.getStandardStringOutputType( System.getenv(stringOutputTypeEnvName)); } } /** * Retrieve the name of the JVM system property which value has been * loaded as the String output type. * * @return the name of the property */ public String getStringOutputTypeSysPropertyName() { return this.stringOutputTypeSysPropertyName; } /** * Set the config object to use the specified JVM system property to * load the value for the String output type. * * @param stringOutputTypeSysPropertyName the name of the property */ public void setStringOutputTypeSysPropertyName(final String stringOutputTypeSysPropertyName) { this.stringOutputTypeSysPropertyName = stringOutputTypeSysPropertyName; if (stringOutputTypeSysPropertyName == null) { this.stringOutputType = null; } else { this.stringOutputTypeEnvName = null; this.stringOutputType = CommonUtils.getStandardStringOutputType( System.getProperty(stringOutputTypeSysPropertyName)); } } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.stringOutputTypeEnvName = null; this.stringOutputTypeSysPropertyName = null; this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); } public String getStringOutputType() { return this.stringOutputType; } } PBECleanablePasswordConfig.java000066400000000000000000000036531360667575700345110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; /** *

* Common interface for all PBEConfig implementations that store passwords as char[] instead * of String and also allow this passwords to be set as char[] instead of Strings. *

* * @since 1.8 * * @author Daniel Fernández * */ public interface PBECleanablePasswordConfig { /** *

* Return the password set, as a char array. *

*

* Important: the returned array MUST BE A COPY of the one * stored in the configuration object. The caller of * this method is therefore be responsible for cleaning this * resulting char[]. *

* * @since 1.8 * */ public char[] getPasswordCharArray(); /** *

* Clean the password stored in this configuration object. *

*

* A common implementation of this cleaning operation consists of * iterating the array of chars and setting each of its positions to (char)0. *

* * @since 1.8 * */ public void cleanPassword(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/PBEConfig.java000066400000000000000000000146631360667575700312610ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import java.security.Provider; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Common interface for config classes applicable to * {@link org.jasypt.encryption.pbe.StandardPBEByteEncryptor}, * {@link org.jasypt.encryption.pbe.StandardPBEStringEncryptor}, * {@link org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor} or * {@link org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor} objects. *

*

* This interface lets the user create new PBEConfig * classes which retrieve values for this parameters from different * (and maybe more secure) sources (remote servers, LDAP, other databases...), * and do this transparently for the encryptor object. *

*

* The config objects passed to an encryptor will only be queried once * for each configuration parameter, and this will happen * during the initialization of the encryptor object. *

*

* For a default implementation, see {@link SimplePBEConfig}. *

* * @since 1.0 * * @author Daniel Fernández * */ public interface PBEConfig { /** *

* Returns the algorithm to be used for encryption, like * PBEWithMD5AndDES. *

* *

* This algorithm has to be supported by the specified JCE provider * (or the default one if no provider has been specified) and, if the * provider supports it, you can also specify mode and * padding for it, like ALGORITHM/MODE/PADDING. *

* * @return the name of the algorithm to be used. */ public String getAlgorithm(); /** *

* Returns the password to be used. *

*

* There is no default value for password, so not setting * this parameter either from a * {@link org.jasypt.encryption.pbe.config.PBEConfig} object or from * a call to setPassword will result in an * EncryptionInitializationException being thrown during initialization. *

* * @return the password to be used. */ public String getPassword(); /** *

* Returns the number of hashing iterations applied to obtain the * encryption key. *

*

* This mechanism is explained in * PKCS #5: Password-Based Cryptography Standard. *

* * @return the number of iterations */ public Integer getKeyObtentionIterations(); /** *

* Returns a {@link SaltGenerator} implementation to be used by the * encryptor. *

*

* If this method returns null, the encryptor will ignore the config object * when deciding the salt generator to be used. *

* * @return the salt generator, or null if this object will not want to set * a specific SaltGenerator implementation. */ public SaltGenerator getSaltGenerator(); /** *

* Returns a {@link IvGenerator} implementation to be used by the * encryptor. *

*

* If this method returns null, the encryptor will ignore the config object * when deciding the IV generator to be used. *

* * @return the IV generator, or null if this object will not want to set * a specific IvGenerator implementation. */ public IvGenerator getIvGenerator(); /** *

* Returns the name of the java.security.Provider implementation * to be used by the encryptor for obtaining the encryption algorithm. This * provider must have been registered beforehand. *

*

* If this method returns null, the encryptor will ignore this parameter * when deciding the name of the security provider to be used. *

*

* If this method does not return null, and neither does {@link #getProvider()}, * providerName will be ignored, and the provider object returned * by getProvider() will be used. *

* * @since 1.3 * * @return the name of the security provider to be used. */ public String getProviderName(); /** *

* Returns the java.security.Provider implementation object * to be used by the encryptor for obtaining the encryption algorithm. *

*

* If this method returns null, the encryptor will ignore this parameter * when deciding the security provider object to be used. *

*

* If this method does not return null, and neither does {@link #getProviderName()}, * providerName will be ignored, and the provider object returned * by getProvider() will be used. *

*

* The provider returned by this method does not need to be * registered beforehand, and its use will not result in its * being registered. *

* * @since 1.3 * * @return the security provider object to be asked for the digest * algorithm. */ public Provider getProvider(); /** *

* Get the size of the pool of encryptors to be created. *

*

* This parameter will be ignored if used with a non-pooled encryptor. *

* * @since 1.7 * * @return the size of the pool to be used if this configuration is used with a * pooled encryptor */ public Integer getPoolSize(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/SimplePBEConfig.java000066400000000000000000000366731360667575700324400ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import java.security.Provider; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.PasswordAlreadyCleanedException; import org.jasypt.iv.IvGenerator; import org.jasypt.salt.SaltGenerator; /** *

* Bean implementation for {@link PBEConfig}. This class allows * the values for the configuration parameters to be set * via "standard" setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

*

* Note that there is not an exact correspondence between setX() * and getX() methods, as sometimes two methods like * setProvider() and setProviderClassName() will affect the * same configuration parameter (getProvider()). This means that * several combinations of setX() methods collide, and * should not be called together (a call to setProviderClassName() * will override any previous call to setProvider()). *

*

* Also note that, in order to satisfy the needs of extreme security-conscious * environments in which no immutable String containing the password is allowed * to be kept in memory, this configuration objects stores the password as char[] * that is cleaned (reset to '') by the jasypt engine as soon as encryption operations * start (and therefore the specified password is no longer needed as an attribute) * (see {@link PBECleanablePasswordConfig}). *

*

* Setting and getting the password as a char[] is also allowed via the * {@link #getPasswordCharArray()} and {@link #setPasswordCharArray(char[])} methods. *

* * @since 1.0 * * @author Daniel Fernández * */ public class SimplePBEConfig implements PBEConfig, PBECleanablePasswordConfig { private String algorithm = null; private char[] password = null; private Integer keyObtentionIterations = null; private SaltGenerator saltGenerator = null; private IvGenerator ivGenerator = null; private String providerName = null; private Provider provider = null; private Integer poolSize = null; private boolean passwordCleaned = false; /** *

* Creates a new SimplePBEConfig instance. *

*/ public SimplePBEConfig() { super(); } /** *

* Sets a value for the encryption algorithm *

*

* This algorithm has to be supported by your JCE provider and, if this provider * supports it, you can also specify mode and padding for * it, like ALGORITHM/MODE/PADDING. *

*

* Determines the result of: {@link #getAlgorithm()} *

* * @param algorithm the name of the algorithm to be used */ public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; } /** * Sets the password to be used for encryption. *

* Determines the result of: {@link #getPassword()} and * {@link #getPasswordCharArray()}. *

* * @param password the password to be used. */ public void setPassword(final String password) { if (this.password != null) { // We clean the old password, if there is one. cleanPassword(); } if (password == null) { this.password = null; } else { this.password = password.toCharArray(); } } /** * Sets the password to be used for encryption, as a char[]. *

* This allows the password to be specified as a cleanable * char[] instead of a String, in extreme security conscious environments * in which no copy of the password as an immutable String should * be kept in memory. *

*

* Important: the array specified as a parameter WILL BE COPIED * in order to be stored in the configuration object. The caller of * this method will therefore be responsible for its cleaning (jasypt * will only clean the internally stored copy). *

*

* Determines the result of: {@link #getPassword()} and * {@link #getPasswordCharArray()}. *

* * @since 1.8 * * @param password the password to be used. */ public void setPasswordCharArray(final char[] password) { if (this.password != null) { // We clean the old password, if there is one. cleanPassword(); } if (password == null) { this.password = null; } else { this.password = new char[password.length]; System.arraycopy(password, 0, this.password, 0, password.length); } } /** * Sets the number of hashing iterations applied to obtain the * encryption key. *

* Determines the result of: {@link #getKeyObtentionIterations()} *

* * @param keyObtentionIterations the number of iterations. */ public void setKeyObtentionIterations(final Integer keyObtentionIterations) { this.keyObtentionIterations = keyObtentionIterations; } /** * Sets the number of hashing iterations applied to obtain the * encryption key. *

* Determines the result of: {@link #getKeyObtentionIterations()} *

* * @since 1.4 * * @param keyObtentionIterations the number of iterations. */ public void setKeyObtentionIterations(final String keyObtentionIterations) { if (keyObtentionIterations != null) { try { this.keyObtentionIterations = new Integer(keyObtentionIterations); } catch (NumberFormatException e) { throw new EncryptionInitializationException(e); } } else { this.keyObtentionIterations = null; } } /** *

* Sets the salt generator. *

*

* If not set, null will returned. *

*

* Determines the result of: {@link #getSaltGenerator()} *

* * @param saltGenerator the salt generator. */ public void setSaltGenerator(final SaltGenerator saltGenerator) { this.saltGenerator = saltGenerator; } /** *

* Sets the salt generator. *

*

* If not set, null will returned. *

*

* Determines the result of: {@link #getSaltGenerator()} *

* * @since 1.4 * * @param saltGeneratorClassName the name of the salt generator class. */ public void setSaltGeneratorClassName(final String saltGeneratorClassName) { if (saltGeneratorClassName != null) { try { final Class saltGeneratorClass = Thread.currentThread().getContextClassLoader().loadClass(saltGeneratorClassName); this.saltGenerator = (SaltGenerator) saltGeneratorClass.newInstance(); } catch (Exception e) { throw new EncryptionInitializationException(e); } } else { this.saltGenerator = null; } } /** *

* Sets the IV generator. *

*

* If not set, null will returned. *

*

* Determines the result of: {@link #getIvGenerator()} *

* * @since 1.9.3 * * @param ivGenerator the IV generator. */ public void setIvGenerator(final IvGenerator ivGenerator) { this.ivGenerator = ivGenerator; } /** *

* Sets the IV generator. *

*

* If not set, null will returned. *

*

* Determines the result of: {@link #getIvGenerator()} *

* * @since 1.9.3 * * @param ivGeneratorClassName the name of the IV generator class. */ public void setIvGeneratorClassName(final String ivGeneratorClassName) { if (ivGeneratorClassName != null) { try { final Class ivGeneratorClass = Thread.currentThread().getContextClassLoader().loadClass(ivGeneratorClassName); this.ivGenerator = (IvGenerator) ivGeneratorClass.newInstance(); } catch (Exception e) { throw new EncryptionInitializationException(e); } } else { this.ivGenerator = null; } } /** *

* Sets the name of the security provider to be asked for the encryption * algorithm. This provider should be already registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the encryptor object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProviderName()} *

* * @since 1.3 * * @param providerName the name of the security provider. */ public void setProviderName(final String providerName) { this.providerName = providerName; } /** *

* Sets the security provider to be used for obtaining the encryption * algorithm. This method is an alternative to * both {@link #setProviderName(String)} and * {@link #setProviderClassName(String)} and they should not be used * altogether. * The provider specified with {@link #setProvider(Provider)} does not * have to be registered beforehand, and its use will not result in its * being registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the encryptor object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProvider()} *

* * @since 1.3 * * @param provider the security provider object. */ public void setProvider(final Provider provider) { this.provider = provider; } /** *

* Sets the security provider to be used for obtaining the encryption * algorithm. This method is an alternative to * both {@link #setProviderName(String)} and {@link #setProvider(Provider)} * and they should not be used altogether. * The provider specified with {@link #setProviderClassName(String)} does not * have to be registered beforehand, and its use will not result in its * being registered. *

*

* If both the providerName and provider properties * are set, only provider will be used, and providerName * will have no meaning for the encryptor object. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getProvider()} *

* * @since 1.4 * * @param providerClassName the name of the security provider class. */ public void setProviderClassName(final String providerClassName) { if (providerClassName != null) { try { final Class providerClass = Thread.currentThread().getContextClassLoader().loadClass(providerClassName); this.provider = (Provider) providerClass.newInstance(); } catch (Exception e) { throw new EncryptionInitializationException(e); } } else { this.provider = null; } } /** *

* Sets the size of the pool of encryptors to be created. *

*

* This parameter will be ignored if used with a non-pooled encryptor. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPoolSize()} *

* * @since 1.7 * * @param poolSize the size of the pool to be used if this configuration is used with a * pooled encryptor */ public void setPoolSize(final Integer poolSize) { this.poolSize = poolSize; } /** *

* Sets the size of the pool of encryptors to be created. *

*

* This parameter will be ignored if used with a non-pooled encryptor. *

*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getPoolSize()} *

* * @since 1.7 * * @param poolSize the size of the pool to be used if this configuration is used with a * pooled encryptor */ public void setPoolSize(final String poolSize) { if (poolSize != null) { try { this.poolSize = new Integer(poolSize); } catch (NumberFormatException e) { throw new EncryptionInitializationException(e); } } else { this.poolSize = null; } } public String getAlgorithm() { return this.algorithm; } public String getPassword() { if (this.passwordCleaned) { throw new PasswordAlreadyCleanedException(); } return new String(this.password); } public char[] getPasswordCharArray() { if (this.passwordCleaned) { throw new PasswordAlreadyCleanedException(); } final char[] result = new char[this.password.length]; System.arraycopy(this.password, 0, result, 0, this.password.length); return result; } public Integer getKeyObtentionIterations() { return this.keyObtentionIterations; } public SaltGenerator getSaltGenerator() { return this.saltGenerator; } public IvGenerator getIvGenerator() { return this.ivGenerator; } public String getProviderName() { return this.providerName; } public Provider getProvider() { return this.provider; } public Integer getPoolSize() { return this.poolSize; } public void cleanPassword() { if (this.password != null) { final int pwdLength = this.password.length; for (int i = 0; i < pwdLength; i++) { this.password[i] = (char)0; } this.password = new char[0]; } this.passwordCleaned = true; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/SimpleStringPBEConfig.java000066400000000000000000000046221360667575700336140ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import org.jasypt.commons.CommonUtils; /** *

* Bean implementation for {@link StringPBEConfig}. This class allows * the values for the configuration parameters to be set * via "standard" setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class SimpleStringPBEConfig extends SimplePBEConfig implements StringPBEConfig { private String stringOutputType = null; /** *

* Creates a new SimpleStringPBEConfig instance. *

*/ public SimpleStringPBEConfig() { super(); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

*

* Determines the result of: {@link #getStringOutputType()} *

* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); } public String getStringOutputType() { return this.stringOutputType; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/StringPBEConfig.java000066400000000000000000000042661360667575700324460ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; /** *

* Common interface for config classes applicable to * {@link org.jasypt.encryption.pbe.StandardPBEStringEncryptor} objects. * This interface extends {@link PBEConfig} to add config parameters specific * to String encryption. *

*

* This interface lets the user create new PBEConfig * classes which retrieve values for this parameters from different * (and maybe more secure) sources (remote servers, LDAP, other databases...), * and do this transparently for the encryptor object. *

*

* The config objects passed to an encryptor will only be queried once * for each configuration parameter, and this will happen * during the initialization of the encryptor object. *

*

* For a default implementation, see {@link SimpleStringPBEConfig}. *

* * @since 1.3 * * @author Daniel Fernández * */ public interface StringPBEConfig extends PBEConfig { /** *

* This parameter lets the user specify the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @return The name of the encoding type for String output */ public String getStringOutputType(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/WebPBEConfig.java000066400000000000000000000112041360667575700317030ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import org.jasypt.commons.CommonUtils; import org.jasypt.web.pbeconfig.WebPBEConfigRegistry; /** *

* Implementation for {@link PBEConfig} which can be used from the * Web PBE Config infrastructure (Filter + Servlet) to set the * password for an encryptor from the web at initialization time. *

*

* For an encryptor to be assigned a password from the web, it only has * to be assigned a WebPBEConfig object, which must be initialized with * both a unique name an a validation word. The name will identify * the config object (and thus the encryptor) and the validation word will * make sure that only an authorized person (for example, the application * deployer) sets the passwords. *

*

* As this class extends {@link SimplePBEConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class WebPBEConfig extends SimplePBEConfig { private String name = null; private String validationWord = null; /** *

* Creates a new WebPBEConfig instance. *

*/ public WebPBEConfig() { super(); final WebPBEConfigRegistry registry = WebPBEConfigRegistry.getInstance(); registry.registerConfig(this); } /** *

* Returns the name by which this WebPBEConfig object will be identified * from the web. This name must be unique for each WebPBEConfig object. *

* * @return the config name. */ public String getName() { return this.name; } /** *

* Sets the name by which this WebPBEConfig object will be identified * from the web. This name must be unique for each WebPBEConfig object. *

* * @param name the unique name which will identify this config object. */ public void setName(final String name) { CommonUtils.validateNotEmpty(name, "Name cannot be set empty"); this.name = name; } /** *

* Returns the validation word which will be asked from the web to the * person setting the password for the encryptor this config object belongs * to. This validation word will make sure that only an authorized person * (for example, the application deployer) sets the value for the * encryption password. *

* * @return the validation word assigned to this config object */ public String getValidationWord() { return this.validationWord; } /** *

* Sets the validation word which will be asked from the web to the * person setting the password for the encryptor this config object belongs * to. This validation word will make sure that only an authorized person * (for example, the application deployer) sets the value for the * encryption password. *

* * @param validation the validation word to be assigned to this config object */ public void setValidationWord(final String validation) { CommonUtils.validateNotEmpty(validation, "Validation word cannot be set empty"); this.validationWord = validation; } /** *

* Returns whether this config object is complete or not (both name and * validation word have been set). Intended for internal use only. *

* * @return whether the config object is complete or not. */ public boolean isComplete() { return ((CommonUtils.isNotEmpty(this.name)) && (CommonUtils.isNotEmpty(this.validationWord))); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/encryption/pbe/config/WebStringPBEConfig.java000066400000000000000000000056661360667575700331110ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe.config; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.StringPBEConfig; /** *

* Implementation for {@link StringPBEConfig} which can be used from the * Web PBE Config infrastructure (Filter + Servlet) to set the * password for an encryptor from the web at initialization time. *

*

* For an encryptor to be assigned a password from the web, it only has * to be assigned a WebPBEConfig object, which must be initialized with * both a unique name an a validation word. The name will identify * the config object (and thus the encryptor) and the validation word will * make sure that only an authorized person (for example, the application * deployer) sets the passwords. *

*

* As this class extends {@link SimplePBEConfig}, parameter values * can be also set with the usual setX methods. *

*

* For any of the configuration parameters, if its setX * method is not called, a null value will be returned by the * corresponding getX method. *

* * @since 1.3 * * @author Daniel Fernández * */ public class WebStringPBEConfig extends WebPBEConfig implements StringPBEConfig { private String stringOutputType = null; /** *

* Creates a new WebStringPBEConfig instance. *

*/ public WebStringPBEConfig() { super(); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
*

* If not set, null will be returned. *

* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.stringOutputType = CommonUtils. getStandardStringOutputType(stringOutputType); } public String getStringOutputType() { return this.stringOutputType; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/exceptions/000077500000000000000000000000001360667575700246245ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/exceptions/AlreadyInitializedException.java000066400000000000000000000024351360667575700331210ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.exceptions; /** * Exception thrown when an attempt is made to change the configuration * of an entity once it has been initialized. * * * @since 1.0 * * @author Daniel Fernández * */ public final class AlreadyInitializedException extends RuntimeException { private static final long serialVersionUID = 4592515503937873874L; public AlreadyInitializedException() { super("Encryption entity already initialized"); } } EncryptionInitializationException.java000066400000000000000000000030131360667575700343260ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/exceptions/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.exceptions; /** * Exception thrown when an error is raised during initialization of * an entity. * * @since 1.0 * * @author Daniel Fernández * */ public final class EncryptionInitializationException extends RuntimeException { private static final long serialVersionUID = 8929638240023639778L; public EncryptionInitializationException() { super(); } public EncryptionInitializationException(final Throwable t) { super(t); } public EncryptionInitializationException(final String msg, final Throwable t) { super(msg, t); } public EncryptionInitializationException(final String msg) { super(msg); } } EncryptionOperationNotPossibleException.java000066400000000000000000000031751360667575700354720ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/exceptions/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.exceptions; /** *

* General exception thrown when any errors are raised during encryption, * digesting, etc. *

*

* It is intended to provide very little information (if any) of the error * causes, so that encryption internals are not revealed through error * messages. *

* * @since 1.0 * * @author Daniel Fernández * */ public final class EncryptionOperationNotPossibleException extends RuntimeException { private static final long serialVersionUID = 6304674109588715145L; public EncryptionOperationNotPossibleException() { super(); } public EncryptionOperationNotPossibleException(final Throwable t) { super(t); } public EncryptionOperationNotPossibleException(final String message) { super(message); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/exceptions/PasswordAlreadyCleanedException.java000066400000000000000000000035211360667575700337270ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.exceptions; /** * Exception thrown when an attempt is made to access the configured * password of an encryptor when this password has already been * cleaned (so that it appears no more as an immutable String in memory). * * * @since 1.8 * * @author Daniel Fernández * */ public final class PasswordAlreadyCleanedException extends RuntimeException { private static final long serialVersionUID = 7988484935273871733L; public PasswordAlreadyCleanedException() { super("Password already cleaned: The encryptor that uses this password has " + "already been initialized and therefore this password has been cleaned so "+ "that it is no more present in memory. An exception has been raised when accessing " + "this property in order to avoid inconsistencies. A possible reason for this error " + "is that you are using the same PBEConfig object to configure two different " + "PBE encryptor instances."); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/000077500000000000000000000000001360667575700234035ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/000077500000000000000000000000001360667575700241525ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/AlgorithmRegistryCLI.java000066400000000000000000000040251360667575700310250ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; import java.util.Set; import org.jasypt.registry.AlgorithmRegistry; /** *

* This class supports the CLI "listAlgorithms" operation. *

*

* It should NEVER be used inside your code, only from the supplied * command-line tools. *

* * @since 1.7 * * @author Daniel Fernández * */ public final class AlgorithmRegistryCLI { /** *

* CLI execution method. *

* * @param args the command execution arguments */ public static void main(final String[] args) { try { final Set digestAlgos = AlgorithmRegistry.getAllDigestAlgorithms(); final Set pbeAlgos = AlgorithmRegistry.getAllPBEAlgorithms(); System.out.println(); System.out.println("DIGEST ALGORITHMS: " + digestAlgos); System.out.println(); System.out.println("PBE ALGORITHMS: " + pbeAlgos); System.out.println(); } catch (Throwable t) { t.printStackTrace(System.err); } } /* * Instantiation is forbidden. */ private AlgorithmRegistryCLI() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/ArgumentNaming.java000066400000000000000000000050071360667575700277330ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; /* * Internal class for holding the names of the CLI parameters. These * can be both direct and environment variable names. */ final class ArgumentNaming { static final String ARG_VERBOSE = "verbose"; static final String ARG_INPUT = "input"; static final String ARG_PASSWORD = "password"; static final String ARG_ALGORITHM = "algorithm"; static final String ARG_ITERATIONS = "iterations"; static final String ARG_KEY_OBTENTION_ITERATIONS = "keyObtentionIterations"; static final String ARG_SALT_SIZE_BYTES = "saltSizeBytes"; static final String ARG_SALT_GENERATOR_CLASS_NAME = "saltGeneratorClassName"; static final String ARG_IV_GENERATOR_CLASS_NAME = "ivGeneratorClassName"; static final String ARG_PROVIDER_CLASS_NAME = "providerClassName"; static final String ARG_PROVIDER_NAME = "providerName"; static final String ARG_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING = "invertPositionOfSaltInMessageBeforeDigesting"; static final String ARG_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS = "invertPositionOfPlainSaltInEncryptionResults"; static final String ARG_USE_LENIENT_SALT_SIZE_CHECK = "useLenientSaltSizeCheck"; static final String ARG_UNICODE_NORMALIZATION_IGNORED = "unicodeNormalizationIgnored"; static final String ARG_STRING_OUTPUT_TYPE = "stringOutputType"; static final String ARG_PREFIX = "prefix"; static final String ARG_SUFFIX = "suffix"; // Instantiation is not allowed private ArgumentNaming() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/CLIUtils.java000066400000000000000000000213551360667575700264530ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; /* * Internal class for managing common CLI operations like argument extraction * or rendering command output/errors. */ final class CLIUtils { /* * Renders the execution environment. */ static void showEnvironment(final boolean verbose) { if (verbose) { System.out.println("\n----ENVIRONMENT-----------------\n"); System.out.println("Runtime: " + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version") + " "); System.out.println("\n"); } } /* * Renders the command arguments as accepted for execution. */ static void showArgumentDescription(final Properties argumentValues, final boolean verbose) { if (verbose) { System.out.println("\n----ARGUMENTS-------------------\n"); final Iterator entriesIter = argumentValues.entrySet().iterator(); while (entriesIter.hasNext()) { final Map.Entry entry = (Map.Entry) entriesIter.next(); System.out.println( entry.getKey() + ": " + entry.getValue()); } System.out.println("\n"); } } /* * Renders the command output. */ static void showOutput(final String output, final boolean verbose) { if (verbose) { System.out.println("\n----OUTPUT----------------------\n"); System.out.println(output); System.out.println("\n"); } else { System.out.println(output); } } /* * Renders an error occurred during execution. */ static void showError(final Throwable t, final boolean verbose) { if (verbose) { System.err.println("\n----ERROR-----------------------\n"); if (t instanceof EncryptionOperationNotPossibleException) { System.err.println( "Operation not possible (Bad input or parameters)"); } else { if (t.getMessage() != null) { System.err.println(t.getMessage()); } else { System.err.println(t.getClass().getName()); } } System.err.println("\n"); } else { System.err.print("ERROR: "); if (t instanceof EncryptionOperationNotPossibleException) { System.err.println( "Operation not possible (Bad input or parameters)"); } else { if (t.getMessage() != null) { System.err.println(t.getMessage()); } else { System.err.println(t.getClass().getName()); } } } } /* * Defines whether the user has turned verbosity off or not. */ static boolean getVerbosity(final String[] args) { for (int i = 0; i < args.length; i++) { final String key = CommonUtils.substringBefore(args[i], "="); final String value = CommonUtils.substringAfter(args[i], "="); if (CommonUtils.isEmpty(key) || CommonUtils.isEmpty(value)) { continue; } if (ArgumentNaming.ARG_VERBOSE.equals(key)) { final Boolean verbosity = CommonUtils.getStandardBooleanValue(value); return (verbosity != null? verbosity.booleanValue() : false); } } return true; } /* * Extracts the argument values and checks its wellformedness. */ static Properties getArgumentValues(final String appName, final String[] args, final String[][] requiredArgNames, final String[][] optionalArgNames) { final Set argNames = new HashSet(); for (int i = 0; i < requiredArgNames.length; i++) { argNames.addAll(Arrays.asList(requiredArgNames[i])); } for (int i = 0; i < optionalArgNames.length; i++) { argNames.addAll(Arrays.asList(optionalArgNames[i])); } final Properties argumentValues = new Properties(); for (int i = 0; i < args.length; i++) { final String key = CommonUtils.substringBefore(args[i], "="); final String value = CommonUtils.substringAfter(args[i], "="); if (CommonUtils.isEmpty(key) || CommonUtils.isEmpty(value)) { throw new IllegalArgumentException("Bad argument: " + args[i]); } if (argNames.contains(key)) { if (value.startsWith("\"") && value.endsWith("\"")) { argumentValues.setProperty( key, value.substring(1, value.length() - 1)); } else { argumentValues.setProperty(key, value); } } else { throw new IllegalArgumentException("Bad argument: " + args[i]); } } //Check for all required arguments for (int i = 0; i < requiredArgNames.length; i++) { boolean found = false; for (int j = 0; j < requiredArgNames[i].length; j++) { if (argumentValues.containsKey(requiredArgNames[i][j])) { found = true; } } if (!found) { showUsageAndExit( appName, requiredArgNames, optionalArgNames); } } return argumentValues; } /* * Renders the usage instructions and exits with error. */ static void showUsageAndExit(final String appName, final String[][] requiredArgNames, final String[][] optionalArgNames) { System.err.println("\nUSAGE: " + appName + " [ARGUMENTS]\n"); System.err.println(" * Arguments must apply to format:\n"); System.err.println( " \"arg1=value1 arg2=value2 arg3=value3 ...\""); System.err.println(); System.err.println(" * Required arguments:\n"); for (int i = 0; i < requiredArgNames.length; i++) { System.err.print(" "); if (requiredArgNames[i].length == 1) { System.err.print(requiredArgNames[i][0]); } else { System.err.print("("); for (int j = 0; j < requiredArgNames[i].length; j++) { if (j > 0) { System.err.print(" | "); } System.err.print(requiredArgNames[i][j]); } System.err.print(")"); } System.err.println(); } System.err.println(); System.err.println(" * Optional arguments:\n"); for (int i = 0; i < optionalArgNames.length; i++) { System.err.print(" "); if (optionalArgNames[i].length == 1) { System.err.print(optionalArgNames[i][0]); } else { System.err.print("("); for (int j = 0; j < optionalArgNames[i].length; j++) { if (j > 0) { System.err.print(" | "); } System.err.print(optionalArgNames[i][j]); } System.err.print(")"); } System.err.println(); } System.exit(1); } /* * Instantiation is forbidden. */ private CLIUtils() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/JasyptPBEStringDecryptionCLI.java000066400000000000000000000124541360667575700324040ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; import java.util.Properties; import org.jasypt.intf.service.JasyptStatelessService; /** *

* This class supports the CLI "decrypt" operation. *

*

* It should NEVER be used inside your code, only from the supplied * command-line tools. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class JasyptPBEStringDecryptionCLI { /* * The required arguments for this CLI operation. */ private static final String[][] VALID_REQUIRED_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_INPUT }, new String [] { ArgumentNaming.ARG_PASSWORD } }; /* * The optional arguments for this CLI operation. */ private static final String[][] VALID_OPTIONAL_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_VERBOSE }, new String [] { ArgumentNaming.ARG_ALGORITHM }, new String [] { ArgumentNaming.ARG_KEY_OBTENTION_ITERATIONS }, new String [] { ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_CLASS_NAME }, new String [] { ArgumentNaming.ARG_STRING_OUTPUT_TYPE }, new String[] { ArgumentNaming.ARG_IV_GENERATOR_CLASS_NAME } }; /** *

* CLI execution method. *

* * @param args the command execution arguments */ public static void main(final String[] args) { boolean verbose = CLIUtils.getVerbosity(args); try { String applicationName = null; String[] arguments = null; if (args[0] == null || args[0].indexOf("=") != -1) { applicationName = JasyptPBEStringDecryptionCLI.class.getName(); arguments = args; } else { applicationName = args[0]; arguments = new String[args.length - 1]; System.arraycopy(args, 1, arguments, 0, args.length - 1); } final Properties argumentValues = CLIUtils.getArgumentValues( applicationName, arguments, VALID_REQUIRED_ARGUMENTS, VALID_OPTIONAL_ARGUMENTS); CLIUtils.showEnvironment(verbose); final JasyptStatelessService service = new JasyptStatelessService(); final String input = argumentValues.getProperty(ArgumentNaming.ARG_INPUT); CLIUtils.showArgumentDescription(argumentValues, verbose); final String result = service.decrypt( input, argumentValues.getProperty(ArgumentNaming.ARG_PASSWORD), null, null, argumentValues.getProperty(ArgumentNaming.ARG_ALGORITHM), null, null, argumentValues.getProperty(ArgumentNaming.ARG_KEY_OBTENTION_ITERATIONS), null, null, argumentValues.getProperty(ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_STRING_OUTPUT_TYPE), null, null, argumentValues.getProperty(ArgumentNaming.ARG_IV_GENERATOR_CLASS_NAME), null, null); CLIUtils.showOutput(result, verbose); } catch (Throwable t) { CLIUtils.showError(t, verbose); } } /* * Instantiation is forbidden. */ private JasyptPBEStringDecryptionCLI() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/JasyptPBEStringEncryptionCLI.java000066400000000000000000000124351360667575700324150ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; import java.util.Properties; import org.jasypt.intf.service.JasyptStatelessService; /** *

* This class supports the CLI "encrypt" operation. *

*

* It should NEVER be used inside your code, only from the supplied * command-line tools. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class JasyptPBEStringEncryptionCLI { /* * The required arguments for this CLI operation. */ private static final String[][] VALID_REQUIRED_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_INPUT }, new String [] { ArgumentNaming.ARG_PASSWORD } }; /* * The optional arguments for this CLI operation. */ private static final String[][] VALID_OPTIONAL_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_VERBOSE }, new String [] { ArgumentNaming.ARG_ALGORITHM }, new String [] { ArgumentNaming.ARG_KEY_OBTENTION_ITERATIONS }, new String [] { ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_CLASS_NAME }, new String [] { ArgumentNaming.ARG_STRING_OUTPUT_TYPE }, new String[] { ArgumentNaming.ARG_IV_GENERATOR_CLASS_NAME } }; /** *

* CLI execution method. *

* * @param args the command execution arguments */ public static void main(final String[] args) { final boolean verbose = CLIUtils.getVerbosity(args); try { String applicationName = null; String[] arguments = null; if (args[0] == null || args[0].indexOf("=") != -1) { applicationName = JasyptPBEStringEncryptionCLI.class.getName(); arguments = args; } else { applicationName = args[0]; arguments = new String[args.length - 1]; System.arraycopy(args, 1, arguments, 0, args.length - 1); } final Properties argumentValues = CLIUtils.getArgumentValues( applicationName, arguments, VALID_REQUIRED_ARGUMENTS, VALID_OPTIONAL_ARGUMENTS); CLIUtils.showEnvironment(verbose); final JasyptStatelessService service = new JasyptStatelessService(); final String input = argumentValues.getProperty(ArgumentNaming.ARG_INPUT); CLIUtils.showArgumentDescription(argumentValues, verbose); final String result = service.encrypt( input, argumentValues.getProperty(ArgumentNaming.ARG_PASSWORD), null, null, argumentValues.getProperty(ArgumentNaming.ARG_ALGORITHM), null, null, argumentValues.getProperty(ArgumentNaming.ARG_KEY_OBTENTION_ITERATIONS), null, null, argumentValues.getProperty(ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_STRING_OUTPUT_TYPE), null, null, argumentValues.getProperty(ArgumentNaming.ARG_IV_GENERATOR_CLASS_NAME), null, null); CLIUtils.showOutput(result, verbose); } catch (Throwable t) { CLIUtils.showError(t, verbose); } } /* * Instantiation is forbidden. */ private JasyptPBEStringEncryptionCLI() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/cli/JasyptStringDigestCLI.java000066400000000000000000000151511360667575700311510ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.cli; import java.util.Properties; import org.jasypt.intf.service.JasyptStatelessService; /** *

* This class supports the CLI "digest" operation. *

*

* It should NEVER be used inside your code, only from the supplied * command-line tools. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class JasyptStringDigestCLI { /* * The required arguments for this CLI operation. */ private static final String[][] VALID_REQUIRED_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_INPUT } }; /* * The optional arguments for this CLI operation. */ private static final String[][] VALID_OPTIONAL_ARGUMENTS = new String[][] { new String [] { ArgumentNaming.ARG_VERBOSE }, new String [] { ArgumentNaming.ARG_ALGORITHM }, new String [] { ArgumentNaming.ARG_ITERATIONS }, new String [] { ArgumentNaming.ARG_SALT_SIZE_BYTES }, new String [] { ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_NAME }, new String [] { ArgumentNaming.ARG_PROVIDER_CLASS_NAME }, new String [] { ArgumentNaming.ARG_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING }, new String [] { ArgumentNaming.ARG_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS }, new String [] { ArgumentNaming.ARG_USE_LENIENT_SALT_SIZE_CHECK }, new String [] { ArgumentNaming.ARG_UNICODE_NORMALIZATION_IGNORED }, new String [] { ArgumentNaming.ARG_STRING_OUTPUT_TYPE }, new String [] { ArgumentNaming.ARG_PREFIX }, new String [] { ArgumentNaming.ARG_SUFFIX } }; /** *

* CLI execution method. *

* * @param args the command execution arguments */ public static void main(final String[] args) { final boolean verbose = CLIUtils.getVerbosity(args); try { String applicationName = null; String[] arguments = null; if (args[0] == null || args[0].indexOf("=") != -1) { applicationName = JasyptStringDigestCLI.class.getName(); arguments = args; } else { applicationName = args[0]; arguments = new String[args.length - 1]; System.arraycopy(args, 1, arguments, 0, args.length - 1); } final Properties argumentValues = CLIUtils.getArgumentValues( applicationName, arguments, VALID_REQUIRED_ARGUMENTS, VALID_OPTIONAL_ARGUMENTS); CLIUtils.showEnvironment(verbose); final JasyptStatelessService service = new JasyptStatelessService(); final String input = argumentValues.getProperty(ArgumentNaming.ARG_INPUT); CLIUtils.showArgumentDescription(argumentValues, verbose); final String result = service.digest( input, argumentValues.getProperty(ArgumentNaming.ARG_ALGORITHM), null, null, argumentValues.getProperty(ArgumentNaming.ARG_ITERATIONS), null, null, argumentValues.getProperty(ArgumentNaming.ARG_SALT_SIZE_BYTES), null, null, argumentValues.getProperty(ArgumentNaming.ARG_SALT_GENERATOR_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_CLASS_NAME), null, null, argumentValues.getProperty(ArgumentNaming.ARG_INVERT_POSITION_OF_SALT_IN_MESSAGE_BEFORE_DIGESTING), null, null, argumentValues.getProperty(ArgumentNaming.ARG_INVERT_POSITION_OF_PLAIN_SALT_IN_ENCRYPTION_RESULTS), null, null, argumentValues.getProperty(ArgumentNaming.ARG_USE_LENIENT_SALT_SIZE_CHECK), null, null, argumentValues.getProperty(ArgumentNaming.ARG_UNICODE_NORMALIZATION_IGNORED), null, null, argumentValues.getProperty(ArgumentNaming.ARG_STRING_OUTPUT_TYPE), null, null, argumentValues.getProperty(ArgumentNaming.ARG_PREFIX), null, null, argumentValues.getProperty(ArgumentNaming.ARG_SUFFIX), null, null); CLIUtils.showOutput(result, verbose); } catch (Throwable t) { CLIUtils.showError(t, verbose); } } /* * Instantiation is forbidden. */ private JasyptStringDigestCLI() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/service/000077500000000000000000000000001360667575700250435ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/intf/service/JasyptStatelessService.java000066400000000000000000000603111360667575700323720ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.intf.service; import org.jasypt.commons.CommonUtils; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; /** *

* This class acts as a stateless service for encryption, decryption and * digest operations, letting its clients configure all the jasypt environment * (algorithms, passwords, providers, initialization vectors...) from Strings in a single call, be it * using direct values, environment variables or java vm properties. *

*

* It is meant to service the CLI interfaces, but it can also be used for other * purposes. For instance, by subclassing or wrapping it with a JAX-WS web * service class, developers can easily create an encryption web service. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class JasyptStatelessService { /** * Creates a new instance of JasyptStatelessService. */ public JasyptStatelessService() { super(); } /** *

* Configure and perform a digest operation. *

* * @param input * @param algorithm * @param algorithmEnvName * @param algorithmSysPropertyName * @param iterations * @param iterationsEnvName * @param iterationsSysPropertyName * @param saltSizeBytes * @param saltSizeBytesEnvName * @param saltSizeBytesSysPropertyName * @param saltGeneratorClassName * @param saltGeneratorClassNameEnvName * @param saltGeneratorClassNameSysPropertyName * @param providerName * @param providerNameEnvName * @param providerNameSysPropertyName * @param providerClassName * @param providerClassNameEnvName * @param providerClassNameSysPropertyName * @param invertPositionOfSaltInMessageBeforeDigesting * @param invertPositionOfSaltInMessageBeforeDigestingEnvName * @param invertPositionOfSaltInMessageBeforeDigestingSysPropertyName * @param invertPositionOfPlainSaltInEncryptionResults * @param invertPositionOfPlainSaltInEncryptionResultsEnvName * @param invertPositionOfPlainSaltInEncryptionResultsSysPropertyName * @param useLenientSaltSizeCheck * @param useLenientSaltSizeCheckEnvName * @param useLenientSaltSizeCheckSysPropertyName * @param unicodeNormalizationIgnored * @param unicodeNormalizationIgnoredEnvName * @param unicodeNormalizationIgnoredSysPropertyName * @param stringOutputType * @param stringOutputTypeEnvName * @param stringOutputTypeSysPropertyName * @param prefix * @param prefixEnvName * @param prefixSysPropertyName * @param suffix * @param suffixEnvName * @param suffixSysPropertyName * * @return the result of the digest operation * @throws EncryptionOperationNotPossibleException if the operation could * not be performed (either because of wrong input or wrong * parametrization). */ public String digest( final String input, final String algorithm, final String algorithmEnvName, final String algorithmSysPropertyName, final String iterations, final String iterationsEnvName, final String iterationsSysPropertyName, final String saltSizeBytes, final String saltSizeBytesEnvName, final String saltSizeBytesSysPropertyName, final String saltGeneratorClassName, final String saltGeneratorClassNameEnvName, final String saltGeneratorClassNameSysPropertyName, final String providerName, final String providerNameEnvName, final String providerNameSysPropertyName, final String providerClassName, final String providerClassNameEnvName, final String providerClassNameSysPropertyName, final String invertPositionOfSaltInMessageBeforeDigesting, final String invertPositionOfSaltInMessageBeforeDigestingEnvName, final String invertPositionOfSaltInMessageBeforeDigestingSysPropertyName, final String invertPositionOfPlainSaltInEncryptionResults, final String invertPositionOfPlainSaltInEncryptionResultsEnvName, final String invertPositionOfPlainSaltInEncryptionResultsSysPropertyName, final String useLenientSaltSizeCheck, final String useLenientSaltSizeCheckEnvName, final String useLenientSaltSizeCheckSysPropertyName, final String unicodeNormalizationIgnored, final String unicodeNormalizationIgnoredEnvName, final String unicodeNormalizationIgnoredSysPropertyName, final String stringOutputType, final String stringOutputTypeEnvName, final String stringOutputTypeSysPropertyName, final String prefix, final String prefixEnvName, final String prefixSysPropertyName, final String suffix, final String suffixEnvName, final String suffixSysPropertyName) { final EnvironmentStringDigesterConfig config = new EnvironmentStringDigesterConfig(); if (algorithmEnvName != null) { config.setAlgorithmEnvName(algorithmEnvName); } if (algorithmSysPropertyName != null) { config.setAlgorithmSysPropertyName(algorithmSysPropertyName); } if (algorithm != null) { config.setAlgorithm(algorithm); } if (iterationsEnvName != null) { config.setIterationsEnvName(iterationsEnvName); } if (iterationsSysPropertyName != null) { config.setIterationsSysPropertyName(iterationsSysPropertyName); } if (iterations != null) { config.setIterations(iterations); } if (saltSizeBytesEnvName != null) { config.setSaltSizeBytesEnvName(saltSizeBytesEnvName); } if (saltSizeBytesSysPropertyName != null) { config.setSaltSizeBytesSysPropertyName(saltSizeBytesSysPropertyName); } if (saltSizeBytes != null) { config.setSaltSizeBytes(saltSizeBytes); } if (saltGeneratorClassNameEnvName != null) { config.setSaltGeneratorClassNameEnvName( saltGeneratorClassNameEnvName); } if (saltGeneratorClassNameSysPropertyName != null) { config.setSaltGeneratorClassNameSysPropertyName( saltGeneratorClassNameSysPropertyName); } if (saltGeneratorClassName != null) { config.setSaltGeneratorClassName(saltGeneratorClassName); } if (providerNameEnvName != null) { config.setProviderNameEnvName(providerNameEnvName); } if (providerNameSysPropertyName != null) { config.setProviderNameSysPropertyName(providerNameSysPropertyName); } if (providerName != null) { config.setProviderName(providerName); } if (providerClassNameEnvName != null) { config.setProviderClassNameEnvName(providerClassNameEnvName); } if (providerClassNameSysPropertyName != null) { config.setProviderClassNameSysPropertyName( providerClassNameSysPropertyName); } if (providerClassName != null) { config.setProviderClassName(providerClassName); } if (invertPositionOfSaltInMessageBeforeDigestingEnvName != null) { config.setInvertPositionOfSaltInMessageBeforeDigestingEnvName(invertPositionOfSaltInMessageBeforeDigestingEnvName); } if (invertPositionOfSaltInMessageBeforeDigestingSysPropertyName != null) { config.setInvertPositionOfSaltInMessageBeforeDigestingSysPropertyName( invertPositionOfSaltInMessageBeforeDigestingSysPropertyName); } if (invertPositionOfSaltInMessageBeforeDigesting != null) { config.setInvertPositionOfSaltInMessageBeforeDigesting( CommonUtils.getStandardBooleanValue(invertPositionOfSaltInMessageBeforeDigesting)); } if (invertPositionOfPlainSaltInEncryptionResultsEnvName != null) { config.setInvertPositionOfPlainSaltInEncryptionResultsEnvName(invertPositionOfPlainSaltInEncryptionResultsEnvName); } if (invertPositionOfPlainSaltInEncryptionResultsSysPropertyName != null) { config.setInvertPositionOfPlainSaltInEncryptionResultsSysPropertyName( invertPositionOfPlainSaltInEncryptionResultsSysPropertyName); } if (invertPositionOfPlainSaltInEncryptionResults != null) { config.setInvertPositionOfPlainSaltInEncryptionResults( CommonUtils.getStandardBooleanValue(invertPositionOfPlainSaltInEncryptionResults)); } if (useLenientSaltSizeCheckEnvName != null) { config.setUseLenientSaltSizeCheckEnvName(useLenientSaltSizeCheckEnvName); } if (useLenientSaltSizeCheckSysPropertyName != null) { config.setUseLenientSaltSizeCheckSysPropertyName( useLenientSaltSizeCheckSysPropertyName); } if (useLenientSaltSizeCheck != null) { config.setUseLenientSaltSizeCheck( CommonUtils.getStandardBooleanValue(useLenientSaltSizeCheck)); } if (unicodeNormalizationIgnoredEnvName != null) { config.setUnicodeNormalizationIgnoredEnvName( unicodeNormalizationIgnoredEnvName); } if (unicodeNormalizationIgnoredSysPropertyName != null) { config.setUnicodeNormalizationIgnoredSysPropertyName( unicodeNormalizationIgnoredSysPropertyName); } if (unicodeNormalizationIgnored != null) { config.setUnicodeNormalizationIgnored(unicodeNormalizationIgnored); } if (stringOutputTypeEnvName != null) { config.setStringOutputTypeEnvName(stringOutputTypeEnvName); } if (stringOutputTypeSysPropertyName != null) { config.setStringOutputTypeSysPropertyName( stringOutputTypeSysPropertyName); } if (stringOutputType != null) { config.setStringOutputType(stringOutputType); } if (prefixEnvName != null) { config.setPrefixEnvName(prefixEnvName); } if (prefixSysPropertyName != null) { config.setPrefixSysPropertyName( prefixSysPropertyName); } if (prefix != null) { config.setPrefix(prefix); } if (suffixEnvName != null) { config.setSuffixEnvName(suffixEnvName); } if (suffixSysPropertyName != null) { config.setSuffixSysPropertyName( suffixSysPropertyName); } if (suffix != null) { config.setSuffix(suffix); } final StandardStringDigester digester = new StandardStringDigester(); digester.setConfig(config); return digester.digest(input); } /** *

* Configure and perform an encryption operation. *

* * @param input * @param password * @param passwordEnvName * @param passwordSysPropertyName * @param algorithm * @param algorithmEnvName * @param algorithmSysPropertyName * @param keyObtentionIterations * @param keyObtentionIterationsEnvName * @param keyObtentionIterationsSysPropertyName * @param saltGeneratorClassName * @param saltGeneratorClassNameEnvName * @param saltGeneratorClassNameSysPropertyName * @param providerName * @param providerNameEnvName * @param providerNameSysPropertyName * @param providerClassName * @param providerClassNameEnvName * @param providerClassNameSysPropertyName * @param stringOutputType * @param stringOutputTypeEnvName * @param stringOutputTypeSysPropertyName * @param ivGeneratorClassName * @param ivGeneratorClassNameEnvName * @param ivGeneratorClassNameSysPropertyName * @return the result of the encryption operation * @throws EncryptionOperationNotPossibleException if the operation could * not be performed (either because of wrong input or wrong * parametrization). */ public String encrypt( final String input, final String password, final String passwordEnvName, final String passwordSysPropertyName, final String algorithm, final String algorithmEnvName, final String algorithmSysPropertyName, final String keyObtentionIterations, final String keyObtentionIterationsEnvName, final String keyObtentionIterationsSysPropertyName, final String saltGeneratorClassName, final String saltGeneratorClassNameEnvName, final String saltGeneratorClassNameSysPropertyName, final String providerName, final String providerNameEnvName, final String providerNameSysPropertyName, final String providerClassName, final String providerClassNameEnvName, final String providerClassNameSysPropertyName, final String stringOutputType, final String stringOutputTypeEnvName, final String stringOutputTypeSysPropertyName, final String ivGeneratorClassName, final String ivGeneratorClassNameEnvName, final String ivGeneratorClassNameSysPropertyName) { final EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); if (algorithmEnvName != null) { config.setAlgorithmEnvName(algorithmEnvName); } if (algorithmSysPropertyName != null) { config.setAlgorithmSysPropertyName(algorithmSysPropertyName); } if (algorithm != null) { config.setAlgorithm(algorithm); } if (keyObtentionIterationsEnvName != null) { config.setKeyObtentionIterationsEnvName( keyObtentionIterationsEnvName); } if (keyObtentionIterationsSysPropertyName != null) { config.setKeyObtentionIterationsSysPropertyName( keyObtentionIterationsSysPropertyName); } if (keyObtentionIterations != null) { config.setKeyObtentionIterations(keyObtentionIterations); } if (passwordEnvName != null) { config.setPasswordEnvName(passwordEnvName); } if (passwordSysPropertyName != null) { config.setPasswordSysPropertyName(passwordSysPropertyName); } if (password != null) { config.setPassword(password); } if (saltGeneratorClassNameEnvName != null) { config.setSaltGeneratorClassNameEnvName( saltGeneratorClassNameEnvName); } if (saltGeneratorClassNameSysPropertyName != null) { config.setSaltGeneratorClassNameSysPropertyName( saltGeneratorClassNameSysPropertyName); } if (saltGeneratorClassName != null) { config.setSaltGeneratorClassName(saltGeneratorClassName); } if (providerNameEnvName != null) { config.setProviderNameEnvName(providerNameEnvName); } if (providerNameSysPropertyName != null) { config.setProviderNameSysPropertyName(providerNameSysPropertyName); } if (providerName != null) { config.setProviderName(providerName); } if (providerClassNameEnvName != null) { config.setProviderClassNameEnvName(providerClassNameEnvName); } if (providerClassNameSysPropertyName != null) { config.setProviderClassNameSysPropertyName( providerClassNameSysPropertyName); } if (providerClassName != null) { config.setProviderClassName(providerClassName); } if (stringOutputTypeEnvName != null) { config.setStringOutputTypeEnvName(stringOutputTypeEnvName); } if (stringOutputTypeSysPropertyName != null) { config.setStringOutputTypeSysPropertyName( stringOutputTypeSysPropertyName); } if (stringOutputType != null) { config.setStringOutputType(stringOutputType); } if (ivGeneratorClassNameEnvName != null) { config.setIvGeneratorClassNameEnvName( ivGeneratorClassNameEnvName); } if (ivGeneratorClassNameSysPropertyName != null) { config.setIvGeneratorClassNameSysPropertyName( ivGeneratorClassNameSysPropertyName); } if (ivGeneratorClassName != null) { config.setIvGeneratorClassName(ivGeneratorClassName); } final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setConfig(config); return encryptor.encrypt(input); } /** *

* Configure and perform a decryption operation. *

* * @param input * @param password * @param passwordEnvName * @param passwordSysPropertyName * @param algorithm * @param algorithmEnvName * @param algorithmSysPropertyName * @param keyObtentionIterations * @param keyObtentionIterationsEnvName * @param keyObtentionIterationsSysPropertyName * @param saltGeneratorClassName * @param saltGeneratorClassNameEnvName * @param saltGeneratorClassNameSysPropertyName * @param providerName * @param providerNameEnvName * @param providerNameSysPropertyName * @param providerClassName * @param providerClassNameEnvName * @param providerClassNameSysPropertyName * @param stringOutputType * @param stringOutputTypeEnvName * @param stringOutputTypeSysPropertyName * @param ivGeneratorClassName * @param ivGeneratorClassNameEnvName * @param ivGeneratorClassNameSysPropertyName * @return the result of the decryption operation * @throws EncryptionOperationNotPossibleException if the operation could * not be performed (either because of wrong input or wrong * parametrization). */ public String decrypt( final String input, final String password, final String passwordEnvName, final String passwordSysPropertyName, final String algorithm, final String algorithmEnvName, final String algorithmSysPropertyName, final String keyObtentionIterations, final String keyObtentionIterationsEnvName, final String keyObtentionIterationsSysPropertyName, final String saltGeneratorClassName, final String saltGeneratorClassNameEnvName, final String saltGeneratorClassNameSysPropertyName, final String providerName, final String providerNameEnvName, final String providerNameSysPropertyName, final String providerClassName, final String providerClassNameEnvName, final String providerClassNameSysPropertyName, final String stringOutputType, final String stringOutputTypeEnvName, final String stringOutputTypeSysPropertyName, final String ivGeneratorClassName, final String ivGeneratorClassNameEnvName, final String ivGeneratorClassNameSysPropertyName) { final EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); if (algorithmEnvName != null) { config.setAlgorithmEnvName(algorithmEnvName); } if (algorithmSysPropertyName != null) { config.setAlgorithmSysPropertyName(algorithmSysPropertyName); } if (algorithm != null) { config.setAlgorithm(algorithm); } if (keyObtentionIterationsEnvName != null) { config.setKeyObtentionIterationsEnvName( keyObtentionIterationsEnvName); } if (keyObtentionIterationsSysPropertyName != null) { config.setKeyObtentionIterationsSysPropertyName( keyObtentionIterationsSysPropertyName); } if (keyObtentionIterations != null) { config.setKeyObtentionIterations(keyObtentionIterations); } if (passwordEnvName != null) { config.setPasswordEnvName(passwordEnvName); } if (passwordSysPropertyName != null) { config.setPasswordSysPropertyName(passwordSysPropertyName); } if (password != null) { config.setPassword(password); } if (saltGeneratorClassNameEnvName != null) { config.setSaltGeneratorClassNameEnvName( saltGeneratorClassNameEnvName); } if (saltGeneratorClassNameSysPropertyName != null) { config.setSaltGeneratorClassNameSysPropertyName( saltGeneratorClassNameSysPropertyName); } if (saltGeneratorClassName != null) { config.setSaltGeneratorClassName(saltGeneratorClassName); } if (providerNameEnvName != null) { config.setProviderNameEnvName(providerNameEnvName); } if (providerNameSysPropertyName != null) { config.setProviderNameSysPropertyName(providerNameSysPropertyName); } if (providerName != null) { config.setProviderName(providerName); } if (providerClassNameEnvName != null) { config.setProviderClassNameEnvName(providerClassNameEnvName); } if (providerClassNameSysPropertyName != null) { config.setProviderClassNameSysPropertyName( providerClassNameSysPropertyName); } if (providerClassName != null) { config.setProviderClassName(providerClassName); } if (stringOutputTypeEnvName != null) { config.setStringOutputTypeEnvName(stringOutputTypeEnvName); } if (stringOutputTypeSysPropertyName != null) { config.setStringOutputTypeSysPropertyName( stringOutputTypeSysPropertyName); } if (stringOutputType != null) { config.setStringOutputType(stringOutputType); } if (ivGeneratorClassNameEnvName != null) { config.setIvGeneratorClassNameEnvName( ivGeneratorClassNameEnvName); } if (ivGeneratorClassNameSysPropertyName != null) { config.setIvGeneratorClassNameSysPropertyName( ivGeneratorClassNameSysPropertyName); } if (ivGeneratorClassName != null) { config.setIvGeneratorClassName(ivGeneratorClassName); } final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setConfig(config); return encryptor.decrypt(input); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/000077500000000000000000000000001360667575700230615ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/ByteArrayFixedIvGenerator.java000066400000000000000000000051601360667575700307560ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* Byte-array based implementation of {@link FixedIvGenerator}, that will * always return the same initialization vector (IV). *

*

* If the requested IV has a size in bytes smaller than the specified IV, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public class ByteArrayFixedIvGenerator implements FixedIvGenerator { private final byte[] iv; /** * Creates a new instance of FixedByteArrayIvGenerator * * @param iv the specified iv. */ public ByteArrayFixedIvGenerator(final byte[] iv) { super(); CommonUtils.validateNotNull(iv, "Initialization vector cannot be set null"); this.iv = (byte[]) iv.clone(); } /** * Return iv with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated iv. */ public byte[] generateIv(final int lengthBytes) { if (this.iv.length < lengthBytes) { throw new EncryptionInitializationException( "Requested initialization vector larger than set"); } final byte[] generatedIv = new byte[lengthBytes]; System.arraycopy(this.iv, 0, generatedIv, 0, lengthBytes); return generatedIv; } /** * As this iv generator provides a fixed iv, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainIvInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/FixedIvGenerator.java000066400000000000000000000022231360667575700271300ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; /** *

* Marker interface for all implementations of {@link IvGenerator} that * will always return the same IV (for the same amount of bytes asked). *

* * @since 1.9.3 * * @author Hoki Torres * */ public interface FixedIvGenerator extends IvGenerator { // Marker interface - no methods added } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/IvGenerator.java000066400000000000000000000043301360667575700261510ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; /** *

* Common interface for all initialization vector (IV) generators which can be applied in * encryption operations. *

*

* Every implementation of this interface must be thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public interface IvGenerator { /** *

* This method will be called for requesting the generation of a new * IV of the specified length. *

* * @param lengthBytes the requested length for the IV. * @return the generated IV. */ public byte[] generateIv(int lengthBytes); /** *

* Determines if the encrypted messages created with a * specific IV generator will include (prepended) the unencrypted * IV itself, so that it can be used for decryption * operations. *

*

* Generally, including the IV unencrypted in encryption results will * be mandatory for randomly generated IV, or for those generated in a * non-predictable manner. * Otherwise, decryption operations will always fail. * For fixed IV, inclusion will be optional (and in fact undesirable * if we want to hide the IV value). *

* * @return whether the plain (unencrypted) IV has to be included in * encryption results or not. */ public boolean includePlainIvInEncryptionResults(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/NoIvGenerator.java000066400000000000000000000033411360667575700264470ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; /** *

* This implementation of {@link IvGenerator} always returns a * initialization vector (IV) of length 0. *

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public class NoIvGenerator implements IvGenerator { /** * Creates a new instance of NoIvGenerator * */ public NoIvGenerator() { super(); } /** * Return IV with 0 byte length. * * @param lengthBytes length in bytes. * @return the generated IV. */ public byte[] generateIv(final int lengthBytes) { return new byte[0]; } /** * As this IV generator provides an empty vector, its inclusion * unencrypted in encryption results is not necessary. * * @return false */ public boolean includePlainIvInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/RandomIvGenerator.java000066400000000000000000000060271360667575700273170ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; import org.jasypt.exceptions.EncryptionInitializationException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; /** *

* This implementation of {@link IvGenerator} holds a secure random * generator which can be used for generating random initialization vectors (IV) for encryption. *

*

* The algorithm used for random number generation can be configured at * instantiation time. If not, the default algorithm will be used. *

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public class RandomIvGenerator implements IvGenerator { /** * The default algorithm to be used for secure random number * generation: set to SHA1PRNG. */ public static final String DEFAULT_SECURE_RANDOM_ALGORITHM = "SHA1PRNG"; private final SecureRandom random; /** * Creates a new instance of RandomIvGenerator using the * default secure random number generation algorithm. */ public RandomIvGenerator() { this(DEFAULT_SECURE_RANDOM_ALGORITHM); } /** * Creates a new instance of RandomIvGenerator specifying a * secure random number generation algorithm. */ public RandomIvGenerator(final String secureRandomAlgorithm) { super(); try { this.random = SecureRandom.getInstance(secureRandomAlgorithm); } catch (NoSuchAlgorithmException e) { throw new EncryptionInitializationException(e); } } /** * Generate a random IV of the specified length in bytes. * * @param lengthBytes length in bytes. * @return the generated IV. */ public byte[] generateIv(final int lengthBytes) { final byte[] iv = new byte[lengthBytes]; synchronized (this.random) { this.random.nextBytes(iv); } return iv; } /** * This IV generator needs the IV to be included unencrypted in * encryption results, because of its being random. This method will always * return true. * * @return true */ public boolean includePlainIvInEncryptionResults() { return true; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/iv/StringFixedIvGenerator.java000066400000000000000000000066671360667575700303370ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.iv; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; import java.io.UnsupportedEncodingException; /** *

* String based implementation of {@link IvGenerator}, that will * always return the same initialization vector (IV). This IV is returned as bytes using the * specified charset for conversion (UTF-8 by default). *

*

* If the requested IV has a size in bytes smaller than the specified IV, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public class StringFixedIvGenerator implements FixedIvGenerator { private static final String DEFAULT_CHARSET = "UTF-8"; private final String iv; private final String charset; private final byte[] ivBytes; /** * Creates a new instance of StringFixedIvGenerator using * the default charset. * * @param iv the specified IV. */ public StringFixedIvGenerator(final String iv) { this(iv, null); } /** * Creates a new instance of StringFixedIvGenerator * * @param iv the specified IV. * @param charset the specified charset */ public StringFixedIvGenerator(final String iv, final String charset) { super(); CommonUtils.validateNotNull(iv, "IV cannot be set null"); this.iv = iv; this.charset = (charset != null? charset : DEFAULT_CHARSET); try { this.ivBytes = this.iv.getBytes(this.charset); } catch (UnsupportedEncodingException e) { throw new EncryptionInitializationException( "Invalid charset specified: " + this.charset); } } /** * Return IV with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated IV. */ public byte[] generateIv(final int lengthBytes) { if (this.ivBytes.length < lengthBytes) { throw new EncryptionInitializationException( "Requested IV larger than set"); } final byte[] generatedIv = new byte[lengthBytes]; System.arraycopy(this.ivBytes, 0, generatedIv, 0, lengthBytes); return generatedIv; } /** * As this IV generator provides a fixed IV, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainIvInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/normalization/000077500000000000000000000000001360667575700253315ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/normalization/Normalizer.java000066400000000000000000000233411360667575700303210ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.normalization; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* Utility for the normalization of Unicode Strings to NFC form. *

*

* This class tries to use the java.text.Normalizer class in JDK 1.6 * first and, if it the class is not found (Java version < 6), then it will use * the ICU4J com.ibm.icu.text.Normalizer class (in this case, a * ClassNotFoundException will be thrown if ICU4J is not present). *

* * @since 1.5 * * @author Daniel Fernández * */ public final class Normalizer { private static final String ICU_NORMALIZER_CLASS_NAME = "com.ibm.icu.text.Normalizer"; private static final String JDK_NORMALIZER_CLASS_NAME = "java.text.Normalizer"; private static final String JDK_NORMALIZER_FORM_CLASS_NAME = "java.text.Normalizer$Form"; private static Boolean useIcuNormalizer = null; private static Method javaTextNormalizerMethod = null; private static Object javaTextNormalizerFormNFCConstant = null; /** *

* Normalize Unicode-input message to NFC. *

*

* This algorithm will first try to normalize the input's UNICODE using icu4j's * com.ibm.icu.text.Normalizer and, if it is not present at the * classpath, will try to use java.text.Normalizer. If this is not present * either (this class appeared in JavaSE 6), it will raise an exception. *

* * @param message the message to be normalized * @return the result of the normalization operation */ public static String normalizeToNfc(final String message) { return new String(normalizeToNfc(message.toCharArray())); } /** *

* Normalize Unicode-input message to NFC. *

*

* This algorithm will first try to normalize the input's UNICODE using icu4j's * com.ibm.icu.text.Normalizer and, if it is not present at the * classpath, will try to use java.text.Normalizer. If this is not present * either (this class appeared in JavaSE 6), it will raise an exception. *

* * @param message the message to be normalized * @return the result of the normalization operation */ public static char[] normalizeToNfc(final char[] message) { if (useIcuNormalizer == null) { // Still not initialized, will try to load the icu4j Normalizer. If // icu4j is in the classpath, it will be used even if java version is >= 6. try { initializeIcu4j(); } catch (final ClassNotFoundException e) { try { initializeJavaTextNormalizer(); } catch (final ClassNotFoundException e2) { throw new EncryptionInitializationException( "Cannot find a valid UNICODE normalizer: neither " + JDK_NORMALIZER_CLASS_NAME + " nor " + ICU_NORMALIZER_CLASS_NAME + " have been found at the classpath. If you are using " + "a version of the JDK older than JavaSE 6, you should include the icu4j library in " + "your classpath."); } catch (final NoSuchMethodException e2) { throw new EncryptionInitializationException( "Cannot find a valid UNICODE normalizer: " + JDK_NORMALIZER_CLASS_NAME + " has " + "been found at the classpath, but has an incompatible signature for its 'normalize' " + "method."); } catch (final NoSuchFieldException e2) { throw new EncryptionInitializationException( "Cannot find a valid UNICODE normalizer: " + JDK_NORMALIZER_FORM_CLASS_NAME + " has " + "been found at the classpath, but seems to have no 'NFC' value."); } catch (final IllegalAccessException e2) { throw new EncryptionInitializationException( "Cannot find a valid UNICODE normalizer: " + JDK_NORMALIZER_FORM_CLASS_NAME + " has " + "been found at the classpath, but seems to have no 'NFC' value."); } } } if (useIcuNormalizer.booleanValue()) { return normalizeWithIcu4j(message); } return normalizeWithJavaNormalizer(message); } static void initializeIcu4j() throws ClassNotFoundException { Thread.currentThread().getContextClassLoader().loadClass(ICU_NORMALIZER_CLASS_NAME); useIcuNormalizer = Boolean.TRUE; } static void initializeJavaTextNormalizer() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException { final Class javaTextNormalizerClass = Thread.currentThread().getContextClassLoader().loadClass(JDK_NORMALIZER_CLASS_NAME); final Class javaTextNormalizerFormClass = Thread.currentThread().getContextClassLoader().loadClass(JDK_NORMALIZER_FORM_CLASS_NAME); javaTextNormalizerMethod = javaTextNormalizerClass.getMethod( "normalize", new Class[]{ CharSequence.class, javaTextNormalizerFormClass }); final Field javaTextNormalizerFormNFCConstantField = javaTextNormalizerFormClass.getField("NFC"); javaTextNormalizerFormNFCConstant = javaTextNormalizerFormNFCConstantField.get(null); useIcuNormalizer = Boolean.FALSE; } static char[] normalizeWithJavaNormalizer(final char[] message) { if (javaTextNormalizerMethod == null || javaTextNormalizerFormNFCConstant == null) { throw new EncryptionInitializationException( "Cannot use: " + JDK_NORMALIZER_FORM_CLASS_NAME + ", as JDK-based normalization has " + "not been initialized! (check previous execution errors)"); } // Using java JDK's Normalizer, we cannot avoid creating Strings // (it is the only possible interface to the Normalizer class). // // Note java.text.Normalizer is accessed via reflection in order to allow this // class to be JDK 1.4-compilable (though ICU4j will be needed at runtime // if Java 1.4 is used). final String messageStr = new String(message); final String result; try { result = (String) javaTextNormalizerMethod.invoke( null, new Object[] { messageStr, javaTextNormalizerFormNFCConstant }); } catch (final Exception e) { throw new EncryptionInitializationException( "Could not perform a valid UNICODE normalization", e); } return result.toCharArray(); } static char[] normalizeWithIcu4j(final char[] message) { // initialize the result to twice the size of the message // this should be more than enough in most cases char[] normalizationResult = new char[message.length * 2]; int normalizationResultSize = 0; while(true) { // Execute normalization. The result will be written into the normalizationResult // char array, and the returned int will be the real size of the result. Normally, // this will be smaller than the size of normalizationResult, but if it is bigger, // we will have to create a new normalizationResult array and try again (icu4j will // not raise an exception, only return a value bigger than the destination array size). normalizationResultSize = com.ibm.icu.text.Normalizer.normalize(message, normalizationResult, com.ibm.icu.text.Normalizer.NFC, 0); if (normalizationResultSize <= normalizationResult.length) { // everything went OK and result fitted. Copy to a correctly-sized array // and clean normalizationResult final char[] result = new char[normalizationResultSize]; System.arraycopy(normalizationResult, 0, result, 0, normalizationResultSize); for (int i = 0; i < normalizationResult.length; i++) { normalizationResult[i] = (char)0; } return result; } // We need a bigger array. the old array must be cleaned also for (int i = 0; i < normalizationResult.length; i++) { normalizationResult[i] = (char)0; } normalizationResult = new char[normalizationResultSize]; } } private Normalizer() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/properties/000077500000000000000000000000001360667575700246375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/properties/EncryptableProperties.java000066400000000000000000000235671360667575700320440ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.properties; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Properties; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.StringEncryptor; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.util.text.TextEncryptor; /** *

* Subclass of java.util.Properties which can make use of a * {@link org.jasypt.encryption.StringEncryptor} or * {@link org.jasypt.util.text.TextEncryptor} object to decrypt property values * if they are encrypted in the .properties file. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

* my.value=ENC(!"DGAS24FaIO$) *
*

*

* Decryption is performed on-the-fly when the {@link #getProperty(String)} or * {@link #getProperty(String, String)} methods are called, and only these two * methods perform decryption (note that neither {@link #get(Object)} nor * {@link #toString()} do). Load and store operations are not affected * by decryption in any manner. *

*

* Encrypted and unencrypted objects can be combined in the same * properties file. *

*

* Please note that, altough objects of this class are Serializable, they * cannot be serialized and then de-serialized in different classloaders or * virtual machines. This is so because encryptors are not serializable themselves * (they cannot, as they contain sensitive information) and so they remain * in memory, and live for as long as the classloader lives. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class EncryptableProperties extends Properties { private static final long serialVersionUID = 6479795856725500639L; /* * Used as an identifier for the encryptor registry */ private final Integer ident = new Integer(CommonUtils.nextRandomInt()); /* * The string encryptor to be used for properties. Either this or the * 'textEncryptor' property have to be non-null. */ private transient StringEncryptor stringEncryptor = null; /* * The text encryptor to be used for properties. Either this or the * 'stringEncryptor' property have to be non-null. */ private transient TextEncryptor textEncryptor = null; /** *

* Creates an EncryptableProperties instance which will use * the passed {@link StringEncryptor} object to decrypt encrypted values. *

* * @param stringEncryptor the {@link StringEncryptor} to be used do decrypt * values. It can not be null. */ public EncryptableProperties(final StringEncryptor stringEncryptor) { this(null, stringEncryptor); } /** *

* Creates an EncryptableProperties instance which will use * the passed {@link TextEncryptor} object to decrypt encrypted values. *

* * @param textEncryptor the {@link TextEncryptor} to be used do decrypt * values. It can not be null. */ public EncryptableProperties(final TextEncryptor textEncryptor) { this(null, textEncryptor); } /** *

* Creates an EncryptableProperties instance which will use * the passed {@link StringEncryptor} object to decrypt encrypted values, * and the passed defaults as default values (may contain encrypted values). *

* * @param defaults default values for properties (may be encrypted). * @param stringEncryptor the {@link StringEncryptor} to be used do decrypt * values. It can not be null. */ public EncryptableProperties(final Properties defaults, final StringEncryptor stringEncryptor) { super(defaults); CommonUtils.validateNotNull(stringEncryptor, "Encryptor cannot be null"); this.stringEncryptor = stringEncryptor; this.textEncryptor = null; } /** *

* Creates an EncryptableProperties instance which will use * the passed {@link TextEncryptor} object to decrypt encrypted values, * and the passed defaults as default values (may contain encrypted values). *

* * @param defaults default values for properties (may be encrypted). * @param textEncryptor the {@link TextEncryptor} to be used do decrypt * values. It can not be null. */ public EncryptableProperties(final Properties defaults, final TextEncryptor textEncryptor) { super(defaults); CommonUtils.validateNotNull(textEncryptor, "Encryptor cannot be null"); this.stringEncryptor = null; this.textEncryptor = textEncryptor; } /** *

* Obtains the property value for the specified key (see * {@link Properties#getProperty(String)}), decrypting it if needed. *

* * @param key the property key * @return the (decrypted) value */ public String getProperty(final String key) { return decode(super.getProperty(key)); } /** *

* Obtains the property value for the specified key (see * {@link Properties#getProperty(String)}), decrypting it if needed. *

*

* If no value is found for the specified key, the default value will * be returned (decrypted if needed). *

* * @param key the property key * @param defaultValue the default value to return * @return the (decrypted) value */ public String getProperty(final String key, final String defaultValue) { return decode(super.getProperty(key, defaultValue)); } /** *

* Obtains the property value for the specified key (see * {@link Hashtable#get(Object)}), decrypting it if needed. *

* * @param key the property key * @return the (decrypted) value * @since 1.9.0 */ public synchronized Object get(final Object key) { final Object value = super.get(key); final String valueStr = (value instanceof String) ? (String)value : null; return decode(valueStr); } /* * Returns the identifier, just to be used by the registry */ Integer getIdent() { return this.ident; } /* * Internal method for decoding (decrypting) a value if needed. */ private synchronized String decode(final String encodedValue) { if (!PropertyValueEncryptionUtils.isEncryptedValue(encodedValue)) { return encodedValue; } if (this.stringEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(encodedValue, this.stringEncryptor); } if (this.textEncryptor != null) { return PropertyValueEncryptionUtils.decrypt(encodedValue, this.textEncryptor); } /* * If neither a StringEncryptor nor a TextEncryptor can be retrieved * from the registry, this means that this EncryptableProperties * object has been serialized and then deserialized in a different * classloader and virtual machine, which is an unsupported behaviour. */ throw new EncryptionOperationNotPossibleException( "Neither a string encryptor nor a text encryptor exist " + "for this instance of EncryptableProperties. This is usually " + "caused by the instance having been serialized and then " + "de-serialized in a different classloader or virtual machine, " + "which is an unsupported behaviour (as encryptors cannot be " + "serialized themselves)"); } private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); final EncryptablePropertiesEncryptorRegistry registry = EncryptablePropertiesEncryptorRegistry.getInstance(); final StringEncryptor registeredStringEncryptor = registry.getStringEncryptor(this); if (registeredStringEncryptor != null) { this.stringEncryptor = registeredStringEncryptor; return; } final TextEncryptor registeredTextEncryptor = registry.getTextEncryptor(this); if (registeredTextEncryptor != null) { this.textEncryptor = registeredTextEncryptor; } } private void writeObject(final ObjectOutputStream outputStream) throws IOException { final EncryptablePropertiesEncryptorRegistry registry = EncryptablePropertiesEncryptorRegistry.getInstance(); if (this.textEncryptor != null) { registry.setTextEncryptor(this, this.textEncryptor); } else if (this.stringEncryptor != null) { registry.setStringEncryptor(this, this.stringEncryptor); } outputStream.defaultWriteObject(); } } EncryptablePropertiesEncryptorRegistry.java000066400000000000000000000054061360667575700354140ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/properties/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.properties; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.jasypt.encryption.StringEncryptor; import org.jasypt.util.text.TextEncryptor; /* * This class acts as a classloader-wide in-memory registry for encryptors, so that * EncryptableProperties instances can be safely serialized (encryptors are not * serializable). * * This means that an EncryptableProperties instance will be de-serializable * only by the same virtual machine that serialized it. * * @since 1.5 * * @author Daniel Fernández * */ final class EncryptablePropertiesEncryptorRegistry { private static final EncryptablePropertiesEncryptorRegistry instance = new EncryptablePropertiesEncryptorRegistry(); private final Map stringEncryptors = Collections.synchronizedMap(new HashMap()); private final Map textEncryptors = Collections.synchronizedMap(new HashMap()); static EncryptablePropertiesEncryptorRegistry getInstance() { return instance; } private EncryptablePropertiesEncryptorRegistry() { super(); } void removeEntries(final EncryptableProperties prop) { this.stringEncryptors.remove(prop.getIdent()); this.textEncryptors.remove(prop.getIdent()); } StringEncryptor getStringEncryptor(final EncryptableProperties prop) { return (StringEncryptor) this.stringEncryptors.get(prop.getIdent()); } void setStringEncryptor(final EncryptableProperties prop, final StringEncryptor encryptor) { this.stringEncryptors.put(prop.getIdent(), encryptor); } TextEncryptor getTextEncryptor(final EncryptableProperties prop) { return (TextEncryptor) this.textEncryptors.get(prop.getIdent()); } void setTextEncryptor(final EncryptableProperties prop, final TextEncryptor encryptor) { this.textEncryptors.put(prop.getIdent(), encryptor); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/properties/PropertyValueEncryptionUtils.java000066400000000000000000000060661360667575700334270ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.properties; import org.jasypt.encryption.StringEncryptor; import org.jasypt.util.text.TextEncryptor; /** *

* Utility class to encrypt/decrypt values in properties files which could be * encrypted. *

*

* A value is considered "encrypted" when it appears surrounded by * ENC(...), like: *

*

*

* my.value=ENC(!"DGAS24FaIO$) *
*

*

* This class is meant for internal Jasypt use only. *

* * @since 1.4 * * @author Daniel Fernández * */ public final class PropertyValueEncryptionUtils { private static final String ENCRYPTED_VALUE_PREFIX = "ENC("; private static final String ENCRYPTED_VALUE_SUFFIX = ")"; public static boolean isEncryptedValue(final String value) { if (value == null) { return false; } final String trimmedValue = value.trim(); return (trimmedValue.startsWith(ENCRYPTED_VALUE_PREFIX) && trimmedValue.endsWith(ENCRYPTED_VALUE_SUFFIX)); } private static String getInnerEncryptedValue(final String value) { return value.substring( ENCRYPTED_VALUE_PREFIX.length(), (value.length() - ENCRYPTED_VALUE_SUFFIX.length())); } public static String decrypt( final String encodedValue, final StringEncryptor encryptor) { return encryptor.decrypt(getInnerEncryptedValue(encodedValue.trim())); } public static String decrypt( final String encodedValue, final TextEncryptor encryptor) { return encryptor.decrypt(getInnerEncryptedValue(encodedValue.trim())); } public static String encrypt( final String decodedValue, final StringEncryptor encryptor) { return ENCRYPTED_VALUE_PREFIX + encryptor.encrypt(decodedValue) + ENCRYPTED_VALUE_SUFFIX; } public static String encrypt( final String decodedValue, final TextEncryptor encryptor) { return ENCRYPTED_VALUE_PREFIX + encryptor.encrypt(decodedValue) + ENCRYPTED_VALUE_SUFFIX; } private PropertyValueEncryptionUtils() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/registry/000077500000000000000000000000001360667575700243135ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/registry/AlgorithmRegistry.java000066400000000000000000000056131360667575700306420ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.registry; import java.security.Security; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** *

* Utility class for retrieving the names of all the digest or encryption * algorithms available to Jasypt. *

*

* This class is thread-safe. *

* * @since 1.7 * * @author Daniel Fernández * */ public final class AlgorithmRegistry { /** *

* Returns a set with the names of all the registered digest algorithms. * This set will also include algorithms from any third-party (non-JVM) registered * providers. *

* * @since 1.7 * * @return a Set of Strings with the names of all the registered * digest algorithms. */ public static Set getAllDigestAlgorithms() { final List algos = new ArrayList(Security.getAlgorithms("MessageDigest")); Collections.sort(algos); return Collections.unmodifiableSet(new LinkedHashSet(algos)); } /** *

* Returns a set with the names of all the registered PBE (Password-Based * Encryption) algorithms. * This set will also include algorithms from any third-party (non-JVM) registered * providers. *

* * @since 1.7 * * @return a Set of Strings with the names of all the registered * PBE algorithms. */ public static Set getAllPBEAlgorithms() { final List algos = new ArrayList(Security.getAlgorithms("Cipher")); Collections.sort(algos); final LinkedHashSet pbeAlgos = new LinkedHashSet(); final Iterator algosIter = algos.iterator(); while (algosIter.hasNext()) { final String algo = (String) algosIter.next(); if (algo != null && algo.startsWith("PBE")) { pbeAlgos.add(algo); } } return Collections.unmodifiableSet(pbeAlgos); } private AlgorithmRegistry() { super(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/000077500000000000000000000000001360667575700234065ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/ByteArrayFixedSaltGenerator.java000066400000000000000000000052041360667575700316270ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* Byte-array based implementation of {@link FixedSaltGenerator}, that will * always return the same salt. *

*

* If the requested salt has a size in bytes smaller than the specified salt, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.9.2 * * @author Daniel Fernández * */ public class ByteArrayFixedSaltGenerator implements FixedSaltGenerator { private final byte[] salt; /** * Creates a new instance of FixedByteArraySaltGenerator * * @param salt the specified salt. */ public ByteArrayFixedSaltGenerator(final byte[] salt) { super(); CommonUtils.validateNotNull(salt, "Salt cannot be set null"); this.salt = (byte[]) salt.clone(); } /** * Return salt with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { if (this.salt.length < lengthBytes) { throw new EncryptionInitializationException( "Requested salt larger than set"); } final byte[] generatedSalt = new byte[lengthBytes]; System.arraycopy(this.salt, 0, generatedSalt, 0, lengthBytes); return generatedSalt; } /** * As this salt generator provides a fixed salt, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainSaltInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/FixedByteArraySaltGenerator.java000066400000000000000000000063021360667575700316270ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* This implementation of {@link SaltGenerator} always returns a fixed salt * set by the user. *

*

* If the requested salt has a size in bytes smaller than the specified salt, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * * @deprecated Deprecated in 1.9.2 in favour of {@link ByteArrayFixedSaltGenerator}, which * implements the new {@link FixedSaltGenerator} interface and therefore is able to benefit * from the performance improvements associated with it. This class will be removed * in 1.10.0 (or 2.0.0). * */ public class FixedByteArraySaltGenerator implements SaltGenerator { private byte[] salt = null; /** * Creates a new instance of FixedByteArraySaltGenerator * */ public FixedByteArraySaltGenerator() { super(); } /** * Sets the salt to be returned. * * @param salt the specified salt. */ public synchronized void setSalt(final byte[] salt) { CommonUtils.validateNotNull(salt, "Salt cannot be set null"); this.salt = (byte[]) salt.clone(); } /** * Return salt with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { if (this.salt == null) { throw new EncryptionInitializationException( "Salt has not been set"); } if (this.salt.length < lengthBytes) { throw new EncryptionInitializationException( "Requested salt larger than set"); } final byte[] generatedSalt = new byte[lengthBytes]; System.arraycopy(this.salt, 0, generatedSalt, 0, lengthBytes); return generatedSalt; } /** * As this salt generator provides a fixed salt, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainSaltInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/FixedSaltGenerator.java000066400000000000000000000025011360667575700300010ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; /** *

* Marker interface for all implementations of {@link SaltGenerator} that * will always return the same salt (for the same amount of bytes asked). *

*

* Use of this interface in salt generators enables encryptors to perform * some performance optimizations whenever they are used. *

* * @since 1.9.2 * * @author Daniel Fernández * */ public interface FixedSaltGenerator extends SaltGenerator { // Marker interface - no methods added } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/FixedStringSaltGenerator.java000066400000000000000000000101671360667575700311770ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import java.io.UnsupportedEncodingException; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* This implementation of {@link SaltGenerator} always returns a fixed salt * set by the user as a String, which is returned as salt bytes using the * specified charset for conversion (UTF-8 by default). *

*

* If the requested salt has a size in bytes smaller than the specified salt, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * * @deprecated Deprecated in 1.9.2 in favour of {@link StringFixedSaltGenerator}, which * implements the new {@link FixedSaltGenerator} interface and therefore is able to benefit * from the performance improvements associated with it. This class will be removed * in 1.10.0 (or 2.0.0). * */ public class FixedStringSaltGenerator implements SaltGenerator { private static final String DEFAULT_CHARSET = "UTF-8"; private String salt = null; private String charset = DEFAULT_CHARSET; private byte[] saltBytes = null; /** * Creates a new instance of FixedStringSaltGenerator * */ public FixedStringSaltGenerator() { super(); } /** * Sets the salt to be returned. * * @param salt the specified salt. */ public synchronized void setSalt(final String salt) { CommonUtils.validateNotNull(salt, "Salt cannot be set null"); this.salt = salt; } /** * Sets the charset to be applied to the salt for conversion into bytes. * * @param charset the specified charset */ public synchronized void setCharset(final String charset) { CommonUtils.validateNotNull(charset, "Charset cannot be set null"); this.charset = charset; } /** * Return salt with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { if (this.salt == null) { throw new EncryptionInitializationException( "Salt has not been set"); } if (this.saltBytes == null) { try { this.saltBytes = this.salt.getBytes(this.charset); } catch (UnsupportedEncodingException e) { throw new EncryptionInitializationException( "Invalid charset specified: " + this.charset); } } if (this.saltBytes.length < lengthBytes) { throw new EncryptionInitializationException( "Requested salt larger than set"); } final byte[] generatedSalt = new byte[lengthBytes]; System.arraycopy(this.saltBytes, 0, generatedSalt, 0, lengthBytes); return generatedSalt; } /** * As this salt generator provides a fixed salt, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainSaltInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/RandomSaltGenerator.java000066400000000000000000000062031360667575700301650ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* This implementation of {@link SaltGenerator} holds a secure random * generator which can be used for generating random salts for encryption * or digesting. *

*

* The algorithm used for random number generation can be configured at * instantiation time. If not, the default algorithm will be used. *

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public class RandomSaltGenerator implements SaltGenerator { /** * The default algorithm to be used for secure random number * generation: set to SHA1PRNG. */ public static final String DEFAULT_SECURE_RANDOM_ALGORITHM = "SHA1PRNG"; private final SecureRandom random; /** * Creates a new instance of RandomSaltGenerator using the * default secure random number generation algorithm. */ public RandomSaltGenerator() { this(DEFAULT_SECURE_RANDOM_ALGORITHM); } /** * Creates a new instance of RandomSaltGenerator specifying a * secure random number generation algorithm. * * @since 1.5 * */ public RandomSaltGenerator(final String secureRandomAlgorithm) { super(); try { this.random = SecureRandom.getInstance(secureRandomAlgorithm); } catch (NoSuchAlgorithmException e) { throw new EncryptionInitializationException(e); } } /** * Generate a random salt of the specified length in bytes. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { final byte[] salt = new byte[lengthBytes]; synchronized (this.random) { this.random.nextBytes(salt); } return salt; } /** * This salt generator needs the salt to be included unencrypted in * encryption results, because of its being random. This method will always * return true. * * @return true */ public boolean includePlainSaltInEncryptionResults() { return true; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/SaltGenerator.java000066400000000000000000000044561360667575700270340ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; /** *

* Common interface for all salt generators which can be applied in digest * or encryption operations. *

*

* Every implementation of this interface must be thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface SaltGenerator { /** *

* This method will be called for requesting the generation of a new * salt of the specified length. *

* * @param lengthBytes the requested length for the salt. * @return the generated salt. */ public byte[] generateSalt(int lengthBytes); /** *

* Determines if the digests and encrypted messages created with a * specific salt generator will include (prepended) the unencrypted * salt itself, so that it can be used for matching and decryption * operations. *

*

* Generally, including the salt unencrypted in encryption results will * be mandatory for randomly generated salts, or for those generated in a * non-predictable manner. * Otherwise, digest matching and decryption operations will always fail. * For fixed salts, inclusion will be optional (and in fact undesirable * if we want to hide the salt value). *

* * @return whether the plain (unencrypted) salt has to be included in * encryption results or not. */ public boolean includePlainSaltInEncryptionResults(); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/StringFixedSaltGenerator.java000066400000000000000000000070271360667575700312000ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import java.io.UnsupportedEncodingException; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* String based implementation of {@link FixedSaltGenerator}, that will * always return the same salt. This salt is returned as bytes using the * specified charset for conversion (UTF-8 by default). *

*

* If the requested salt has a size in bytes smaller than the specified salt, * the first n bytes are returned. If it is larger, an exception is thrown. *

*

* This class is thread-safe. *

* * @since 1.9.2 * * @author Daniel Fernández * */ public class StringFixedSaltGenerator implements FixedSaltGenerator { private static final String DEFAULT_CHARSET = "UTF-8"; private final String salt; private final String charset; private final byte[] saltBytes; /** * Creates a new instance of FixedStringSaltGenerator using * the default charset. * * @param salt the specified salt. */ public StringFixedSaltGenerator(final String salt) { this(salt, null); } /** * Creates a new instance of FixedStringSaltGenerator * * @param salt the specified salt. * @param charset the specified charset */ public StringFixedSaltGenerator(final String salt, final String charset) { super(); CommonUtils.validateNotNull(salt, "Salt cannot be set null"); this.salt = salt; this.charset = (charset != null? charset : DEFAULT_CHARSET); try { this.saltBytes = this.salt.getBytes(this.charset); } catch (UnsupportedEncodingException e) { throw new EncryptionInitializationException( "Invalid charset specified: " + this.charset); } } /** * Return salt with the specified byte length. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { if (this.saltBytes.length < lengthBytes) { throw new EncryptionInitializationException( "Requested salt larger than set"); } final byte[] generatedSalt = new byte[lengthBytes]; System.arraycopy(this.saltBytes, 0, generatedSalt, 0, lengthBytes); return generatedSalt; } /** * As this salt generator provides a fixed salt, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainSaltInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/salt/ZeroSaltGenerator.java000066400000000000000000000040641360667575700276670ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.salt; import java.util.Arrays; /** *

* This implementation of {@link SaltGenerator} always returns a salt * of the required length, filled with zero bytes. *

*

* This class is thread-safe. *

* * @since 1.4 * * @author Daniel Fernández * */ public class ZeroSaltGenerator implements SaltGenerator { /** * Creates a new instance of ZeroSaltGenerator * */ public ZeroSaltGenerator() { super(); } /** * Return salt with the specified byte length. This will return * an array of zero bytes, with the specified length. * * @param lengthBytes length in bytes. * @return the generated salt. */ public byte[] generateSalt(final int lengthBytes) { final byte[] result = new byte[lengthBytes]; Arrays.fill(result, (byte)0); return result; } /** * As this salt generator provides a predictable salt, its inclusion * unencrypted in encryption results * is not necessary, and in fact not desirable (so that it remains hidden). * * @return false */ public boolean includePlainSaltInEncryptionResults() { return false; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/000077500000000000000000000000001360667575700234205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/binary/000077500000000000000000000000001360667575700247045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/binary/AES256BinaryEncryptor.java000066400000000000000000000063501360667575700314730ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; import org.jasypt.iv.RandomIvGenerator; /** *

* Utility class for easily performing high-strength encryption of * binaries (byte arrays). *

*

* This class internally holds a {@link StandardPBEByteEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithHMACSHA512AndAES_256.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(byte[])} or * {@link #decrypt(byte[])} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class AES256BinaryEncryptor implements BinaryEncryptor { // The internal encryptor private final StandardPBEByteEncryptor encryptor; /** * Creates a new instance of StrongBinaryEncryptor. */ public AES256BinaryEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); this.encryptor.setIvGenerator(new RandomIvGenerator()); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a byte array * * @param binary the byte array to be encrypted. * @see StandardPBEByteEncryptor#encrypt(byte[]) */ public byte[] encrypt(final byte[] binary) { return this.encryptor.encrypt(binary); } /** * Decrypts a byte array. * * @param encryptedBinary the byte array to be decrypted. * @see StandardPBEByteEncryptor#decrypt(byte[]) */ public byte[] decrypt(final byte[] encryptedBinary) { return this.encryptor.decrypt(encryptedBinary); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/binary/BasicBinaryEncryptor.java000066400000000000000000000062261360667575700316510ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; /** *

* Utility class for easily performing normal-strength encryption of * binaries (byte arrays). *

*

* This class internally holds a {@link StandardPBEByteEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(byte[])} or * {@link #decrypt(byte[])} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class BasicBinaryEncryptor implements BinaryEncryptor { // The internal encryptor private final StandardPBEByteEncryptor encryptor; /** * Creates a new instance of BasicBinaryEncryptor. */ public BasicBinaryEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a byte array * * @param binary the byte array to be encrypted. * @see StandardPBEByteEncryptor#encrypt(byte[]) */ public byte[] encrypt(final byte[] binary) { return this.encryptor.encrypt(binary); } /** * Decrypts a byte array. * * @param encryptedBinary the byte array to be decrypted. * @see StandardPBEByteEncryptor#decrypt(byte[]) */ public byte[] decrypt(final byte[] encryptedBinary) { return this.encryptor.decrypt(encryptedBinary); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/binary/BinaryEncryptor.java000066400000000000000000000025461360667575700307100ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; /** *

* Common interface for all util classes aimed at binary encryption *

* * @since 1.2 * * @author Daniel Fernández * */ public interface BinaryEncryptor { /** * Encrypts a byte array * * @param binary the byte array to be encrypted. */ public byte[] encrypt(byte[] binary); /** * Decrypts a byte array. * * @param encryptedBinary the byte array to be decrypted. */ public byte[] decrypt(byte[] encryptedBinary); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/binary/StrongBinaryEncryptor.java000066400000000000000000000062431360667575700321030ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; /** *

* Utility class for easily performing high-strength encryption of * binaries (byte arrays). *

*

* This class internally holds a {@link StandardPBEByteEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndTripleDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(byte[])} or * {@link #decrypt(byte[])} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class StrongBinaryEncryptor implements BinaryEncryptor { // The internal encryptor private final StandardPBEByteEncryptor encryptor; /** * Creates a new instance of StrongBinaryEncryptor. */ public StrongBinaryEncryptor() { super(); this.encryptor = new StandardPBEByteEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a byte array * * @param binary the byte array to be encrypted. * @see StandardPBEByteEncryptor#encrypt(byte[]) */ public byte[] encrypt(final byte[] binary) { return this.encryptor.encrypt(binary); } /** * Decrypts a byte array. * * @param encryptedBinary the byte array to be decrypted. * @see StandardPBEByteEncryptor#decrypt(byte[]) */ public byte[] decrypt(final byte[] encryptedBinary) { return this.encryptor.decrypt(encryptedBinary); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/digest/000077500000000000000000000000001360667575700246775ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/digest/Digester.java000066400000000000000000000200371360667575700273120ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.digest; import java.security.Provider; import org.jasypt.digest.StandardByteDigester; /** *

* Utility class for creating digests without using a salt or iterating * the hash function. This means that digests created by this class will * be compatible (and equivalent) to the ones which could be created by * the user by directly using a {@link java.security.MessageDigest} object. *

*

* This class can be thought of as convenience wrapper for * {@link java.security.MessageDigest}, adding thread-safety and * a more javabean-like interface to it. These two features enable a more * adequate use from an IoC container like Spring. *

*

* This class internally holds a {@link StandardByteDigester} * configured this way: *

    *
  • Algorithm: MD5 by default, but configurable.
  • *
  • Provider: Default JVM security provider, but configurable.
  • *
  • Salt size: 0 bytes, no salt used.
  • *
  • Iterations: 1, hash function will not be iterated.
  • *
*

*

* This class is thread-safe *

* * @since 1.2 (class existed as org.jasypt.util.MessageDigester since 1.1) * * @author Daniel Fernández * */ public final class Digester { /** * MD5 will be the default algorithm to be used if none is specified. */ public static final String DEFAULT_ALGORITHM = "MD5"; // The hash function will be applied only once private static final int ITERATIONS = 1; // No salt will be used private static final int SALT_SIZE_BYTES = 0; // The internal digester used private final StandardByteDigester digester; /** * Creates a new instance of Digester. It will use * the default algorithm unless one is specified with * {@link #setAlgorithm(String)}. * */ public Digester() { super(); this.digester = new StandardByteDigester(); this.digester.setIterations(ITERATIONS); this.digester.setSaltSizeBytes(SALT_SIZE_BYTES); } /** *

* Creates a new instance of Digester, specifying * the algorithm to be used. *

*/ public Digester(final String algorithm) { super(); this.digester = new StandardByteDigester(); this.digester.setIterations(ITERATIONS); this.digester.setSaltSizeBytes(SALT_SIZE_BYTES); this.digester.setAlgorithm(algorithm); } /** *

* Creates a new instance of Digester, specifying * the algorithm to be used. *

* * @since 1.3 */ public Digester(final String algorithm, final String providerName) { super(); this.digester = new StandardByteDigester(); this.digester.setIterations(ITERATIONS); this.digester.setSaltSizeBytes(SALT_SIZE_BYTES); this.digester.setAlgorithm(algorithm); this.digester.setProviderName(providerName); } /** *

* Creates a new instance of Digester, specifying * the algorithm to be used. *

* * @since 1.3 */ public Digester(final String algorithm, final Provider provider) { super(); this.digester = new StandardByteDigester(); this.digester.setIterations(ITERATIONS); this.digester.setSaltSizeBytes(SALT_SIZE_BYTES); this.digester.setAlgorithm(algorithm); this.digester.setProvider(provider); } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. * @throws AlreadyInitializedException if it has already been initialized, * this is, if {@link #digest(byte[])} has been called at least * once. */ public void setAlgorithm(final String algorithm) { this.digester.setAlgorithm(algorithm); } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the digest algorithm. * @throws AlreadyInitializedException if it has already been initialized, * this is, if {@link #digest(byte[])} has been called at least * once. */ public void setProviderName(final String providerName) { this.digester.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * it being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm * @throws AlreadyInitializedException if it has already been initialized, * this is, if {@link #digest(byte[])} has been called at least * once. */ public void setProvider(final Provider provider) { this.digester.setProvider(provider); } /** * Creates a digest. * * @param binary the byte array to be digested. * @return the resulting digest. * @see StandardByteDigester#digest(byte[]) */ public byte[] digest(final byte[] binary) { return this.digester.digest(binary); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/000077500000000000000000000000001360667575700250625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/AES256DecimalNumberEncryptor.java000066400000000000000000000065211360667575700331340ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; import org.jasypt.iv.RandomIvGenerator; import java.math.BigDecimal; /** *

* Utility class for easily performing normal-strength encryption of * BigDecimal objects. *

*

* This class internally holds a {@link StandardPBEBigDecimalEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithHMACSHA512AndAES_256.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigDecimal)} or * {@link #decrypt(BigDecimal)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class AES256DecimalNumberEncryptor implements DecimalNumberEncryptor { // The internal encryptor private final StandardPBEBigDecimalEncryptor encryptor; /** * Creates a new instance of StrongDecimalNumberEncryptor. */ public AES256DecimalNumberEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); this.encryptor.setIvGenerator(new RandomIvGenerator()); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigDecimalEncryptor#encrypt(BigDecimal) */ public BigDecimal encrypt(final BigDecimal number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigDecimalEncryptor#decrypt(BigDecimal) */ public BigDecimal decrypt(final BigDecimal encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/AES256IntegerNumberEncryptor.java000066400000000000000000000065211360667575700331730ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; import org.jasypt.iv.RandomIvGenerator; import java.math.BigInteger; /** *

* Utility class for easily performing normal-strength encryption of * BigInteger objects. *

*

* This class internally holds a {@link StandardPBEBigIntegerEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithHMACSHA512AndAES_256.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigInteger)} or * {@link #decrypt(BigInteger)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class AES256IntegerNumberEncryptor implements IntegerNumberEncryptor { // The internal encryptor private final StandardPBEBigIntegerEncryptor encryptor; /** * Creates a new instance of StrongIntegerNumberEncryptor. */ public AES256IntegerNumberEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); this.encryptor.setIvGenerator(new RandomIvGenerator()); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigIntegerEncryptor#encrypt(BigInteger) */ public BigInteger encrypt(final BigInteger number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigIntegerEncryptor#decrypt(BigInteger) */ public BigInteger decrypt(final BigInteger encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/BasicDecimalNumberEncryptor.java000066400000000000000000000063721360667575700333140ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigDecimal; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; /** *

* Utility class for easily performing normal-strength encryption of * BigDecimal objects. *

*

* This class internally holds a {@link StandardPBEBigDecimalEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigDecimal)} or * {@link #decrypt(BigDecimal)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class BasicDecimalNumberEncryptor implements DecimalNumberEncryptor { // The internal encryptor private final StandardPBEBigDecimalEncryptor encryptor; /** * Creates a new instance of BasicDecimalNumberEncryptor. */ public BasicDecimalNumberEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigDecimalEncryptor#encrypt(BigDecimal) */ public BigDecimal encrypt(final BigDecimal number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigDecimalEncryptor#decrypt(BigDecimal) */ public BigDecimal decrypt(final BigDecimal encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/BasicIntegerNumberEncryptor.java000066400000000000000000000063721360667575700333530ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigInteger; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; /** *

* Utility class for easily performing normal-strength encryption of * BigInteger objects. *

*

* This class internally holds a {@link StandardPBEBigIntegerEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigInteger)} or * {@link #decrypt(BigInteger)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class BasicIntegerNumberEncryptor implements IntegerNumberEncryptor { // The internal encryptor private final StandardPBEBigIntegerEncryptor encryptor; /** * Creates a new instance of BasicIntegerNumberEncryptor. */ public BasicIntegerNumberEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigIntegerEncryptor#encrypt(BigInteger) */ public BigInteger encrypt(final BigInteger number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigIntegerEncryptor#decrypt(BigInteger) */ public BigInteger decrypt(final BigInteger encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/DecimalNumberEncryptor.java000066400000000000000000000026331360667575700323460ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigDecimal; /** *

* Common interface for all util classes aimed at decimal number encryption. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface DecimalNumberEncryptor { /** * Encrypts a BigDecimal * * @param number the number to be encrypted. */ public BigDecimal encrypt(BigDecimal number); /** * Decrypts a BigDecimal. * * @param encryptedNumber the number to be decrypted. */ public BigDecimal decrypt(BigDecimal encryptedNumber); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/IntegerNumberEncryptor.java000066400000000000000000000026331360667575700324050ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigInteger; /** *

* Common interface for all util classes aimed at integer number encryption. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface IntegerNumberEncryptor { /** * Encrypts a BigInteger * * @param number the number to be encrypted. */ public BigInteger encrypt(BigInteger number); /** * Decrypts a BigInteger. * * @param encryptedNumber the number to be decrypted. */ public BigInteger decrypt(BigInteger encryptedNumber); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/StrongDecimalNumberEncryptor.java000066400000000000000000000064121360667575700335420ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigDecimal; import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor; /** *

* Utility class for easily performing normal-strength encryption of * BigDecimal objects. *

*

* This class internally holds a {@link StandardPBEBigDecimalEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndTripleDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigDecimal)} or * {@link #decrypt(BigDecimal)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class StrongDecimalNumberEncryptor implements DecimalNumberEncryptor { // The internal encryptor private final StandardPBEBigDecimalEncryptor encryptor; /** * Creates a new instance of StrongDecimalNumberEncryptor. */ public StrongDecimalNumberEncryptor() { super(); this.encryptor = new StandardPBEBigDecimalEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigDecimalEncryptor#encrypt(BigDecimal) */ public BigDecimal encrypt(final BigDecimal number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigDecimalEncryptor#decrypt(BigDecimal) */ public BigDecimal decrypt(final BigDecimal encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/numeric/StrongIntegerNumberEncryptor.java000066400000000000000000000064121360667575700336010ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigInteger; import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor; /** *

* Utility class for easily performing normal-strength encryption of * BigInteger objects. *

*

* This class internally holds a {@link StandardPBEBigIntegerEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndTripleDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(BigInteger)} or * {@link #decrypt(BigInteger)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 * * @author Daniel Fernández * */ public final class StrongIntegerNumberEncryptor implements IntegerNumberEncryptor { // The internal encryptor private final StandardPBEBigIntegerEncryptor encryptor; /** * Creates a new instance of StrongIntegerNumberEncryptor. */ public StrongIntegerNumberEncryptor() { super(); this.encryptor = new StandardPBEBigIntegerEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a number * * @param number the number to be encrypted. * @see StandardPBEBigIntegerEncryptor#encrypt(BigInteger) */ public BigInteger encrypt(final BigInteger number) { return this.encryptor.encrypt(number); } /** * Decrypts a number. * * @param encryptedNumber the number to be decrypted. * @see StandardPBEBigIntegerEncryptor#decrypt(BigInteger) */ public BigInteger decrypt(final BigInteger encryptedNumber) { return this.encryptor.decrypt(encryptedNumber); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/000077500000000000000000000000001360667575700252625ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/BasicPasswordEncryptor.java000066400000000000000000000057221360667575700326050ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import org.jasypt.digest.StandardStringDigester; /** *

* Utility class for easily performing password digesting and checking. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: MD5.
  • *
  • Salt size: 8 bytes.
  • *
  • Iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Perform the desired {@link #encryptPassword(String)} or * {@link #checkPassword(String, String)} * operations.
  4. *
*

*

* This class is thread-safe *

* * @since 1.2 (class existed as org.jasypt.util.PasswordEncryptor since 1.0) * * @author Daniel Fernández * */ public final class BasicPasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of BasicPasswordEncryptor * */ public BasicPasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.initialize(); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/ConfigurablePasswordEncryptor.java000066400000000000000000000210631360667575700341600ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import java.security.Provider; import org.jasypt.digest.StandardByteDigester; import org.jasypt.digest.StandardStringDigester; import org.jasypt.digest.config.DigesterConfig; /** *

* Utility class for easily performing password digesting and checking. *

*

* This class internally holds a {@link StandardStringDigester} * which can be configured by the user by optionally choosing the algorithm * to be used, the output format (BASE64 or hexadecimal) the mechanism of * encryption (plain digests vs. use of random salt * and iteration count (default)) and even use a {@link DigesterConfig} object for * more advanced configuration. *

*

* The results obtained when encoding with this class are encoded in * BASE64 form. *

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Configure if needed with the setX() methods.
  4. *
  5. Perform the desired {@link #encryptPassword(String)} or * {@link #checkPassword(String, String)} * operations.
  6. *
*

*

* This class is thread-safe *

* * @since 1.2 * * @author Daniel Fernández * */ public final class ConfigurablePasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of ConfigurablePasswordEncryptor * */ public ConfigurablePasswordEncryptor() { super(); this.digester = new StandardStringDigester(); } /** * Lets the user configure this encryptor with a {@link DigesterConfig} * object, like if he/she were using a {@link StandardStringDigester} object * directly. * * @param config the DigesterConfig object to be set for configuration. * @see StandardStringDigester#setConfig(DigesterConfig) */ public void setConfig(final DigesterConfig config) { this.digester.setConfig(config); } /** *

* Sets the algorithm to be used for digesting, like MD5 * or SHA-1. *

*

* This algorithm has to be supported by your security infrastructure, and * it should be allowed as an algorithm for creating * java.security.MessageDigest instances. *

*

* If you are specifying a security provider with {@link #setProvider(Provider)} or * {@link #setProviderName(String)}, this algorithm should be * supported by your specified provider. *

*

* If you are not specifying a provider, you will be able to use those * algorithms provided by the default security provider of your JVM vendor. * For valid names in the Sun JVM, see Java * Cryptography Architecture API Specification & * Reference. *

* * @param algorithm the name of the algorithm to be used. * @see StandardStringDigester#setAlgorithm(String) */ public void setAlgorithm(final String algorithm) { this.digester.setAlgorithm(algorithm); } /** *

* Sets the name of the security provider to be asked for the * digest algorithm. This security provider has to be registered beforehand * at the JVM security framework. *

*

* The provider can also be set with the {@link #setProvider(Provider)} * method, in which case it will not be necessary neither registering * the provider beforehand, * nor calling this {@link #setProviderName(String)} method to specify * a provider name. *

*

* Note that a call to {@link #setProvider(Provider)} overrides any value * set by this method. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param providerName the name of the security provider to be asked * for the digest algorithm. * @throws AlreadyInitializedException if it has already been initialized, * this is, if {@link #encryptPassword(String)} or * {@link #checkPassword(String, String)} have been called at least * once. */ public void setProviderName(final String providerName) { this.digester.setProviderName(providerName); } /** *

* Sets the security provider to be asked for the digest algorithm. * The provider does not have to be registered at the security * infrastructure beforehand, and its being used here will not result in * it being registered. *

*

* If this method is called, calling {@link #setProviderName(String)} * becomes unnecessary. *

*

* If no provider name / provider is explicitly set, the default JVM * provider will be used. *

* * @since 1.3 * * @param provider the provider to be asked for the chosen algorithm * @throws AlreadyInitializedException if it has already been initialized, * this is, if {@link #encryptPassword(String)} or * {@link #checkPassword(String, String)} have been called at least * once. */ public void setProvider(final Provider provider) { this.digester.setProvider(provider); } /** * Lets the user specify if he/she wants a plain digest used as an * encryption mechanism (no salt or iterations, as with * {@link java.security.MessageDigest}), or rather use the * jasypt's usual stronger mechanism for password encryption (based * on the use of a salt and the iteration of the hash function). * * @param plainDigest true for using plain digests, false for the strong * salt and iteration count based mechanism. */ public void setPlainDigest(final boolean plainDigest) { if (plainDigest) { this.digester.setIterations(1); this.digester.setSaltSizeBytes(0); } else { this.digester.setIterations(StandardByteDigester.DEFAULT_ITERATIONS); this.digester.setSaltSizeBytes(StandardByteDigester.DEFAULT_SALT_SIZE_BYTES); } } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* @since 1.3 * * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.digester.setStringOutputType(stringOutputType); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/PasswordEncryptor.java000066400000000000000000000032441360667575700316400ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; /** *

* Common interface for all util classes aimed at password encryption. *

* * @since 1.2 * * @author Daniel Fernández * */ public interface PasswordEncryptor { /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. */ public String encryptPassword(String password); /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. */ public boolean checkPassword(String plainPassword, String encryptedPassword); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/StrongPasswordEncryptor.java000066400000000000000000000061541360667575700330400ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import org.jasypt.digest.StandardStringDigester; /** *

* Utility class for easily performing high-strength password * digesting and checking. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: SHA-256.
  • *
  • Salt size: 16 bytes.
  • *
  • Iterations: 100000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Perform the desired {@link #encryptPassword(String)} or * {@link #checkPassword(String, String)} * operations.
  4. *
*

*

* This class is thread-safe *

* * @since 1.2 (class existed in org.jasypt.util package since 1.1) * * @author Daniel Fernández * */ public final class StrongPasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of StrongPasswordEncryptor * */ public StrongPasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.setAlgorithm("SHA-256"); this.digester.setIterations(100000); this.digester.setSaltSizeBytes(16); this.digester.initialize(); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/rfc2307/000077500000000000000000000000001360667575700263505ustar00rootroot00000000000000RFC2307MD5PasswordEncryptor.java000066400000000000000000000067101360667575700340250ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/rfc2307/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password.rfc2307; import org.jasypt.digest.StandardStringDigester; import org.jasypt.util.password.PasswordEncryptor; /** *

* Utility class for easily performing password digesting and checking * according to {MD5}, a password encryption scheme defined in RFC2307 * and commonly found in LDAP systems. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: MD5.
  • *
  • Salt size: 0 bytes (no salt).
  • *
  • Iterations: 1 (no hash iteration).
  • *
  • Prefix: {MD5}.
  • *
*

*

* This class is thread-safe *

* * @since 1.7 * * @author Daniel Fernández * */ public final class RFC2307MD5PasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of RFC2307MD5PasswordEncryptor * */ public RFC2307MD5PasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.setAlgorithm("MD5"); this.digester.setIterations(1); this.digester.setSaltSizeBytes(0); this.digester.setPrefix("{MD5}"); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.digester.setStringOutputType(stringOutputType); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } RFC2307SHAPasswordEncryptor.java000066400000000000000000000067211360667575700340550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/rfc2307/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password.rfc2307; import org.jasypt.digest.StandardStringDigester; import org.jasypt.util.password.PasswordEncryptor; /** *

* Utility class for easily performing password digesting and checking * according to {SHA}, a password encryption scheme defined in RFC2307 * and commonly found in LDAP systems. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: SHA-1.
  • *
  • Salt size: 0 bytes (no salt).
  • *
  • Iterations: 1 (no hash iteration).
  • *
  • Prefix: {SHA}.
  • *
*

*

* This class is thread-safe *

* * @since 1.7 * * @author Daniel Fernández * */ public final class RFC2307SHAPasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of RFC2307SHAPasswordEncryptor * */ public RFC2307SHAPasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.setAlgorithm("SHA-1"); this.digester.setIterations(1); this.digester.setSaltSizeBytes(0); this.digester.setPrefix("{SHA}"); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.digester.setStringOutputType(stringOutputType); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** * Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. * * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } RFC2307SMD5PasswordEncryptor.java000066400000000000000000000106571360667575700341550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/rfc2307/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password.rfc2307; import org.jasypt.digest.StandardStringDigester; import org.jasypt.util.password.PasswordEncryptor; /** *

* Utility class for easily performing password digesting and checking * according to {SMD5}, a password encryption scheme defined in RFC2307 * and commonly found in LDAP systems. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: MD5.
  • *
  • Salt size: 8 bytes (configurable with {@link #setSaltSizeBytes(int)}).
  • *
  • Iterations: 1 (no hash iteration).
  • *
  • Prefix: {SMD5}.
  • *
  • Invert position of salt in message before digesting: true.
  • *
  • Invert position of plain salt in encryption results: true.
  • *
  • Use lenient salt size check: true.
  • . *
*

*

* This class is thread-safe *

* * @since 1.7 * * @author Daniel Fernández * */ public final class RFC2307SMD5PasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of RFC2307OpenLDAPSSHAPasswordEncryptor * */ public RFC2307SMD5PasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.setAlgorithm("MD5"); this.digester.setIterations(1); this.digester.setSaltSizeBytes(8); this.digester.setPrefix("{SMD5}"); this.digester.setInvertPositionOfSaltInMessageBeforeDigesting(true); this.digester.setInvertPositionOfPlainSaltInEncryptionResults(true); this.digester.setUseLenientSaltSizeCheck(true); } /** *

* Sets the size (in bytes) of the salt to be used. *

*

* Default is 8. *

* * @param saltSizeBytes the salt size in bytes */ public void setSaltSizeBytes(final int saltSizeBytes) { this.digester.setSaltSizeBytes(saltSizeBytes); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.digester.setStringOutputType(stringOutputType); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** *

* Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. *

*

* This password encryptor expects encrypted passwords being matched to * include the "{SMD5}" prefix, and will fail if not. *

* * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } RFC2307SSHAPasswordEncryptor.java000066400000000000000000000106631360667575700342000ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/password/rfc2307/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password.rfc2307; import org.jasypt.digest.StandardStringDigester; import org.jasypt.util.password.PasswordEncryptor; /** *

* Utility class for easily performing password digesting and checking * according to {SSHA}, a password encryption scheme defined in RFC2307 * and commonly found in LDAP systems. *

*

* This class internally holds a {@link StandardStringDigester} * configured this way: *

    *
  • Algorithm: SHA-1.
  • *
  • Salt size: 8 bytes (configurable with {@link #setSaltSizeBytes(int)}).
  • *
  • Iterations: 1 (no hash iteration).
  • *
  • Prefix: {SSHA}.
  • *
  • Invert position of salt in message before digesting: true.
  • *
  • Invert position of plain salt in encryption results: true.
  • *
  • Use lenient salt size check: true.
  • . *
*

*

* This class is thread-safe *

* * @since 1.7 * * @author Daniel Fernández * */ public final class RFC2307SSHAPasswordEncryptor implements PasswordEncryptor { // The internal digester used private final StandardStringDigester digester; /** * Creates a new instance of RFC2307OpenLDAPSSHAPasswordEncryptor * */ public RFC2307SSHAPasswordEncryptor() { super(); this.digester = new StandardStringDigester(); this.digester.setAlgorithm("SHA-1"); this.digester.setIterations(1); this.digester.setSaltSizeBytes(8); this.digester.setPrefix("{SSHA}"); this.digester.setInvertPositionOfSaltInMessageBeforeDigesting(true); this.digester.setInvertPositionOfPlainSaltInEncryptionResults(true); this.digester.setUseLenientSaltSizeCheck(true); } /** *

* Sets the size (in bytes) of the salt to be used. *

*

* Default is 8. *

* * @param saltSizeBytes the salt size in bytes */ public void setSaltSizeBytes(final int saltSizeBytes) { this.digester.setSaltSizeBytes(saltSizeBytes); } /** *

* Sets the the form in which String output * will be encoded. Available encoding types are: *

*
    *
  • base64 (default)
  • *
  • hexadecimal
  • *
* * @param stringOutputType the string output type. */ public void setStringOutputType(final String stringOutputType) { this.digester.setStringOutputType(stringOutputType); } /** * Encrypts (digests) a password. * * @param password the password to be encrypted. * @return the resulting digest. * @see StandardStringDigester#digest(String) */ public String encryptPassword(final String password) { return this.digester.digest(password); } /** *

* Checks an unencrypted (plain) password against an encrypted one * (a digest) to see if they match. *

*

* This password encryptor expects encrypted passwords being matched to * include the "{SSHA}" prefix, and will fail if not. *

* * @param plainPassword the plain password to check. * @param encryptedPassword the digest against which to check the password. * @return true if passwords match, false if not. * @see StandardStringDigester#matches(String, String) */ public boolean checkPassword(final String plainPassword, final String encryptedPassword) { return this.digester.matches(plainPassword, encryptedPassword); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/text/000077500000000000000000000000001360667575700244045ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/text/AES256TextEncryptor.java000066400000000000000000000063211360667575700306710ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2019, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.iv.RandomIvGenerator; /** *

* Utility class for easily performing high-strength encryption of texts. *

*

* This class internally holds a {@link StandardPBEStringEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithHMACSHA512AndAES_256".
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(String)} or * {@link #decrypt(String)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.9.3 * * @author Hoki Torres * */ public final class AES256TextEncryptor implements TextEncryptor { // The internal encryptor private final StandardPBEStringEncryptor encryptor; /** * Creates a new instance of StrongTextEncryptor. */ public AES256TextEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); this.encryptor.setIvGenerator(new RandomIvGenerator()); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a message. * * @param message the message to be encrypted. * @see StandardPBEStringEncryptor#encrypt(String) */ public String encrypt(final String message) { return this.encryptor.encrypt(message); } /** * Decrypts a message. * * @param encryptedMessage the message to be decrypted. * @see StandardPBEStringEncryptor#decrypt(String) */ public String decrypt(final String encryptedMessage) { return this.encryptor.decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/text/BasicTextEncryptor.java000066400000000000000000000062671360667575700310560ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; /** *

* Utility class for easily performing normal-strength encryption of texts. *

*

* This class internally holds a {@link StandardPBEStringEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(String)} or * {@link #decrypt(String)} operations.
  6. *
*

*

* This class is thread-safe. *

* * @since 1.2 (class existed as org.jasypt.util.TextEncryptor since 1.0) * * @author Daniel Fernández * */ public final class BasicTextEncryptor implements TextEncryptor { // The internal encryptor private final StandardPBEStringEncryptor encryptor; /** * Creates a new instance of BasicTextEncryptor. */ public BasicTextEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[] * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a message. * * @param message the message to be encrypted. * @see StandardPBEStringEncryptor#encrypt(String) */ public String encrypt(final String message) { return this.encryptor.encrypt(message); } /** * Decrypts a message. * * @param encryptedMessage the message to be decrypted. * @see StandardPBEStringEncryptor#decrypt(String) */ public String decrypt(final String encryptedMessage) { return this.encryptor.decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/text/StrongTextEncryptor.java000066400000000000000000000066651360667575700313130ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; /** *

* Utility class for easily performing high-strength encryption of texts. *

*

* This class internally holds a {@link StandardPBEStringEncryptor} * configured this way: *

    *
  • Algorithm: PBEWithMD5AndTripleDES.
  • *
  • Key obtention iterations: 1000.
  • *
*

*

* The required steps to use it are: *

    *
  1. Create an instance (using new).
  2. *
  3. Set a password (using {@link #setPassword(String)} or * {@link #setPasswordCharArray(char[])}).
  4. *
  5. Perform the desired {@link #encrypt(String)} or * {@link #decrypt(String)} operations.
  6. *
*

*

* To use this class, you may need to download and install the * Java * Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy * Files. *

*

* This class is thread-safe. *

* * @since 1.2 (class existed in org.jasypt.util package since 1.0) * * @author Daniel Fernández * */ public final class StrongTextEncryptor implements TextEncryptor { // The internal encryptor private final StandardPBEStringEncryptor encryptor; /** * Creates a new instance of StrongTextEncryptor. */ public StrongTextEncryptor() { super(); this.encryptor = new StandardPBEStringEncryptor(); this.encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); } /** * Sets a password. * * @param password the password to be set. */ public void setPassword(final String password) { this.encryptor.setPassword(password); } /** * Sets a password, as a char[]. * * @since 1.8 * @param password the password to be set. */ public void setPasswordCharArray(final char[] password) { this.encryptor.setPasswordCharArray(password); } /** * Encrypts a message. * * @param message the message to be encrypted. * @see StandardPBEStringEncryptor#encrypt(String) */ public String encrypt(final String message) { return this.encryptor.encrypt(message); } /** * Decrypts a message. * * @param encryptedMessage the message to be decrypted. * @see StandardPBEStringEncryptor#decrypt(String) */ public String decrypt(final String encryptedMessage) { return this.encryptor.decrypt(encryptedMessage); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/util/text/TextEncryptor.java000066400000000000000000000025311360667575700301020ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; /** *

* Common interface for all util classes aimed at text encryption *

* * @since 1.2 * * @author Daniel Fernández * */ public interface TextEncryptor { /** * Encrypts a message. * * @param message the message to be encrypted. */ public String encrypt(String message); /** * Decrypts a message. * * @param encryptedMessage the message to be decrypted. */ public String decrypt(String encryptedMessage); } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/000077500000000000000000000000001360667575700232205ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/000077500000000000000000000000001360667575700251545ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/WebPBEConfigFilter.java000066400000000000000000000056221360667575700313640ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** *

* This filter is intended to avoid access to the web application until * an admin has set the encryption passwords. It will query the web PBE config * system to know whether passwords have been set and, if not, it will show the * user a plain Access Forbidden page. *

*

* An example web.xml fragment (being applied on a Struts servlet): *

*
 *    <filter>
 *        <filter-name>webPBEConfigFilter</filter-name>
 *        <filter-class>org.jasypt.web.pbeconfig.WebPBEConfigFilter</filter-class>
 *    </filter>
 *
 *    <filter-mapping>
 *        <filter-name>webPBEConfigFilter</filter-name>
 *        <servlet-name>strutsActionServlet</servlet-name>
 *    </filter-mapping>    
 * 
* * @since 1.3 * * @author Daniel Fernández * */ public final class WebPBEConfigFilter implements Filter { public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final WebPBEConfigRegistry registry = WebPBEConfigRegistry.getInstance(); if (registry.isWebConfigurationDone()) { // If it is initialized, quickly continue filter chain chain.doFilter(request, response); } else { // Not initialized, a Forbidden page must be shown, chain broken PrintWriter printWriter = response.getWriter(); printWriter.write(WebPBEConfigHtmlUtils.createNotInitializedHtml()); printWriter.flush(); } } public void init(final FilterConfig filterConfig) throws ServletException { // Nothing to be done here. } public void destroy() { // Nothing to be done here. } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/WebPBEConfigHtmlUtils.java000066400000000000000000000146611360667575700320670ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.jasypt.encryption.pbe.config.WebPBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* HTML creation class for internal use of {@link WebPBEConfigServlet} and * {@link WebPBEConfigFilter}. *

* * @since 1.3 * * @author Daniel Fernández * */ final class WebPBEConfigHtmlUtils { public static final String PASSWORD_SETTING_FLAG = "jasyptPwSetting"; public static final String VALIDATION_PREFIX = "jasyptVa"; public static final String PASSWORD_PREFIX = "jasyptPw"; public static final String PASSWORD_RETYPED_PREFIX = "jasyptRPw"; private static final String HTTPS_SCHEME = "https"; private WebPBEConfigHtmlUtils() { super(); } public static String createConfigurationDoneHtml() { final StringBuffer strBuff = new StringBuffer(); addHeader(strBuff); strBuff.append("

All Configuration Done

\n"); addFoot(strBuff); return strBuff.toString(); } public static String createInputFormHtml( final HttpServletRequest request, final boolean inputError) { final WebPBEConfigRegistry registry = WebPBEConfigRegistry.getInstance(); final List configs = registry.getConfigs(); final StringBuffer strBuff = new StringBuffer(); addHeader(strBuff); strBuff.append("

Please enter the PBE configuration parameters

\n"); if (!HTTPS_SCHEME.equals(request.getScheme().toLowerCase())) { strBuff.append("
WARNING: NOT IN SECURE MODE (HTTPS)
\n"); } if (inputError) { strBuff.append("
Validation error!
\n"); } strBuff.append("
\n"); strBuff.append("
\n"); final Iterator configsIter = configs.iterator(); int i = 0; while (configsIter.hasNext()) { WebPBEConfig config = (WebPBEConfig) configsIter.next(); if (!config.isComplete()) { throw new EncryptionInitializationException("Incomplete " + "WebPBEConfig object: all configs must specify " + "both a name and a validation word"); } strBuff.append("
\n"); strBuff.append(" " + config.getName() + "\n"); strBuff.append(" : \n"); strBuff.append("

\n"); strBuff.append(" : \n"); strBuff.append("

\n"); strBuff.append(" : \n"); strBuff.append("
\n"); i++; } strBuff.append("
\n"); strBuff.append("
\n"); strBuff.append(" \n"); strBuff.append(" \n"); strBuff.append("
\n"); strBuff.append("
\n"); addFoot(strBuff); return strBuff.toString(); } public static String createNotInitializedHtml() { final StringBuffer strBuff = new StringBuffer(); strBuff.append("\n"); strBuff.append(" \n"); strBuff.append(" Forbidden\n"); strBuff.append(" \n"); strBuff.append(" \n"); strBuff.append("

Access Forbidden

\n"); strBuff.append(" \n"); strBuff.append("\n"); return strBuff.toString(); } private static void addHeader(final StringBuffer strBuff) { strBuff.append("\n"); strBuff.append(" \n"); strBuff.append(" Web Password Based Encryption Configuration\n"); strBuff.append(" \n"); strBuff.append(" \n"); strBuff.append(" \n"); strBuff.append("
\n"); strBuff.append("

Web PBE Configuration

\n"); } private static void addFoot(final StringBuffer strBuff) { strBuff.append("
\n"); strBuff.append(" \n"); strBuff.append("\n"); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/WebPBEConfigRegistry.java000066400000000000000000000052341360667575700317460ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jasypt.encryption.pbe.config.WebPBEConfig; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* Registry for {@link WebPBEConfig} objects. This class is intended * for internal use only, and should not be accessed from the user's * code. *

* * @since 1.3 * * @author Daniel Fernández * */ public final class WebPBEConfigRegistry { private final Set names = new HashSet(); private final List configs = new ArrayList(); private boolean webConfigurationDone = false; private static final WebPBEConfigRegistry instance = new WebPBEConfigRegistry(); public static WebPBEConfigRegistry getInstance() { return instance; } private WebPBEConfigRegistry() { super(); } public synchronized void registerConfig(final WebPBEConfig config) { if (this.webConfigurationDone) { throw new EncryptionInitializationException( "Cannot register: Web configuration is already done"); } // Avoid duplication of encryptors because of the initialization // class being called more than once. if (!this.names.contains(config.getName())) { this.configs.add(config); this.names.add(config); } } public synchronized List getConfigs() { return Collections.unmodifiableList(this.configs); } public boolean isWebConfigurationDone() { return (this.webConfigurationDone || (this.configs.size() == 0)); } public void setWebConfigurationDone(final boolean configurationDone) { this.webConfigurationDone = configurationDone; } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/WebPBEConfigServlet.java000066400000000000000000000216311360667575700315610ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasypt.commons.CommonUtils; import org.jasypt.encryption.pbe.config.WebPBEConfig; /** *

* Servlet for web PBE config processing. *

*

* This servlet's URL should be called by the webapp administrator at deploy * time, for setting the passwords of all the PBE encryptors which have * been previously assigned a {@link WebPBEConfig} configuration object. *

*

* If web PBE configuration has not been done yet, it will show the user a * form containing two inputs for each encryptor: the validation word * and the password (retyped). *

*
    *
  • The validation word must be input to the value set on the * {@link WebPBEConfig} object with its setValidationWord(...) * method. This will ensure that only an authorized person will set * the encryption passwords.
  • . *
  • The password (retyped) must be input to the value which is * desired to be the encryption password for each specific encryptor.
  • *
*

* An example web.xml fragment: *

*
 *  <servlet>
 *    <servlet-name>webPBEConfigServlet</servlet-name>
 *    <servlet-class>
 *      org.jasypt.web.pbeconfig.WebPBEConfigServlet
 *    </servlet-class>
 *    <load-on-startup>1</load-on-startup>
 *  </servlet>
 *
 *  <servlet-mapping>
 *    <servlet-name>webPBEConfigServlet</servlet-name>
 *    <url-pattern>/webPBEConfig.do</url-pattern>
 *  </servlet-mapping>
 * 
*

* If this servlet's context is set a logger, it will output messages for * both successful and failed attempts to set passwords, including * date, time and originating IP address. *

* * @since 1.3 * * @author Daniel Fernández * */ public final class WebPBEConfigServlet extends HttpServlet { private static final long serialVersionUID = -7201635392816652667L; protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { execute(req, resp); } protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { execute(req, resp); } private void execute(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { try { final WebPBEConfigRegistry registry = WebPBEConfigRegistry.getInstance(); if (registry.isWebConfigurationDone()) { // Configuration was already done, display an "Already done" page writeResponse( WebPBEConfigHtmlUtils.createConfigurationDoneHtml(), resp); } else { final String settingFlag = req.getParameter(WebPBEConfigHtmlUtils.PASSWORD_SETTING_FLAG); if (CommonUtils.isEmpty(settingFlag)) { // We are first arriving at the form, just show it writeResponse( WebPBEConfigHtmlUtils.createInputFormHtml(req, false), resp); } else { /* * The form was already shown and submitted, so we must * process the results. */ final List configs = registry.getConfigs(); Iterator configsIter = configs.iterator(); int i = 0; int valid = 0; while (configsIter.hasNext()) { final WebPBEConfig config = (WebPBEConfig) configsIter.next(); final String validation = req.getParameter(WebPBEConfigHtmlUtils.VALIDATION_PREFIX + i); final String password = req.getParameter(WebPBEConfigHtmlUtils.PASSWORD_PREFIX + i); final String retypedPassword = req.getParameter(WebPBEConfigHtmlUtils.PASSWORD_RETYPED_PREFIX + i); if (!CommonUtils.isEmpty(validation) && !CommonUtils.isEmpty(password) && password.equals(retypedPassword) && (config.getValidationWord().equals(validation))) { /* * Passwords will not be set here, instead, we will * wait until ALL the passwords are set correctly, * to avoid a partial initialization. */ valid++; } i++; } final SimpleDateFormat dateFormat = new SimpleDateFormat(); final Calendar now = Calendar.getInstance(); if (valid < configs.size()) { /* * Bad attempt: log and show error. */ this.getServletContext().log( "Failed attempt to set PBE Configuration from " + req.getRemoteAddr() + " [" + dateFormat.format(now.getTime()) + "]"); writeResponse( WebPBEConfigHtmlUtils.createInputFormHtml(req, true), resp); } else { /* * Success: log, set passwords and show success page. */ configsIter = configs.iterator(); i = 0; while (configsIter.hasNext()) { WebPBEConfig config = (WebPBEConfig) configsIter.next(); String password = req.getParameter(WebPBEConfigHtmlUtils.PASSWORD_PREFIX + i); config.setPassword(password); i++; } registry.setWebConfigurationDone(true); this.getServletContext().log( "PBE Configuration succesfully set from " + req.getRemoteAddr() + " [" + dateFormat.format(now.getTime()) + "]"); writeResponse( WebPBEConfigHtmlUtils.createConfigurationDoneHtml(), resp); } } } } catch (IOException e) { this.getServletContext().log( "Exception raised during servlet execution", e); throw e; } catch (Throwable t) { this.getServletContext().log( "Exception raised during servlet execution", t); throw new ServletException(t); } } private void writeResponse(final String html, final HttpServletResponse response) throws IOException { final PrintWriter printWriter = response.getWriter(); printWriter.write(html); printWriter.flush(); } } WebPBEInitializationContextListener.java000066400000000000000000000100641360667575700347700ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.jasypt.commons.CommonUtils; import org.jasypt.exceptions.EncryptionInitializationException; /** *

* ContextListener which takes a {@link WebPBEInitializer} implementation * class name as a parameter (<context-param>) and calls its * initializeWebPBEConfigs() method to allow the webapp to * create its PBE encryptors and declare their associated {@link WebPBEConfig} * objects. *

*

* An example web.xml fragment: *

*
 *    <context-param>
 *      <param-name>webPBEInitializerClassName</param-name>
 *      <param-value>myapp.MyWebPBEInitializer</param-value>
 *    </context-param>
 *
 *    <listener>
 *      <listener-class>
 *        org.jasypt.web.pbeconfig.WebPBEInitializationContextListener
 *      </listener-class>
 *    </listener>
 * 
*

* Important: If the web application uses Spring Framework, WebPBEConfig * objects are declared as beans in the Spring context and this Spring context * is initialized at application deploy time * (with Spring's ContextLoaderListener), the use * of this context listener will become unnecessary. *

* * @since 1.3 * * @author Daniel Fernández * */ public final class WebPBEInitializationContextListener implements ServletContextListener { public static final String INIT_PARAM_INITIALIZER_CLASS_NAME = "webPBEInitializerClassName"; public void contextDestroyed(final ServletContextEvent sce) { // nothing to be done here } public void contextInitialized(final ServletContextEvent sce) { final String className = sce.getServletContext().getInitParameter( INIT_PARAM_INITIALIZER_CLASS_NAME); if (CommonUtils.isEmpty(className)) { throw new EncryptionInitializationException( INIT_PARAM_INITIALIZER_CLASS_NAME + " context " + "initialization parameter not set in web.xml"); } Class initializerClass = null; try { initializerClass = Thread.currentThread().getContextClassLoader().loadClass(className); } catch (ClassNotFoundException e) { throw new EncryptionInitializationException(e); } if (!WebPBEInitializer.class.isAssignableFrom(initializerClass)) { throw new EncryptionInitializationException("Class " + className + " does not implement interface " + WebPBEInitializer.class.getName()); } WebPBEInitializer initializer = null; try { initializer = (WebPBEInitializer) initializerClass.newInstance(); } catch (InstantiationException e) { throw new EncryptionInitializationException(e); } catch (IllegalAccessException e) { throw new EncryptionInitializationException(e); } // Let the user initialize his/her encryptors and WebPBEConfig objects. initializer.initializeWebPBEConfigs(); } } jasypt-jasypt-1.9.3/jasypt/src/main/java/org/jasypt/web/pbeconfig/WebPBEInitializer.java000066400000000000000000000060611360667575700312720ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.web.pbeconfig; /** *

* Interface which must be implemented by the user-defined classes which * create and initialize webapp PBE encryptors for being configured through * the web pbe configuration servlet. *

*

* This interface only has one method, {@link #initializeWebPBEConfigs()}, * which the implementation class should use for creating encryptors and * setting {@link WebPBEConfig} objects to them, like: *

*
 *  package myapp;
 *  ... 
 *  public class MyWebPBEInitializer implements WebPBEInitializer {
 *  
 *      public void initializeWebPBEConfigs() {
 *      
 *          StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
 *          encryptor.setAlgorithm("PBEWithMD5AndDES");
 *          
 *          WebPBEConfig webConfig = new WebPBEConfig();
 *          webConfig.setValidationWord("jasypt");
 *          webConfig.setName("Main Password");
 *
 *          encryptor.setConfig(webConfig);
 *          
 *          // Get some user-defined singleton or similar, and register
 *          // the encryptor with it so that it can be accessed from the
 *          // rest of the application.
 *          
 *      }
 *      
 *  }
 * 
*

* All WebPBEConfig objects get internally registered at * instantiation time, and once assigned to an encryptor they will appear * in the web form for password setting. *

*

* Important: If the web application uses Spring Framework, WebPBEConfig * objects are declared as beans in the Spring context and this Spring context * is initialized at application deploy time * (with Spring's ContextLoaderListener), it will NOT be necessary * to create * any classes implementing this WebPBEInitializer interface. * The use {@link WebPBEInitializationContextListener} will also become * unnecessary. *

* * @since 1.3 * * @author Daniel Fernández * */ public interface WebPBEInitializer { /** *

* Method called by {@link WebPBEInitializationContextListener} at * application deploy time for initialization of jasypt encryptors. *

* */ public void initializeWebPBEConfigs(); } jasypt-jasypt-1.9.3/jasypt/src/test/000077500000000000000000000000001360667575700174545ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/000077500000000000000000000000001360667575700203755ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/000077500000000000000000000000001360667575700211645ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/000077500000000000000000000000001360667575700224765ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/000077500000000000000000000000001360667575700237555ustar00rootroot00000000000000PooledStandardStringDigesterThreadedTest.java000066400000000000000000000126371360667575700346340ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.time.StopWatch; public class PooledStandardStringDigesterThreadedTest extends TestCase { private int numThreads = 20; private int numIters = 1000; protected int poolSize = 2; public PooledStandardStringDigesterThreadedTest() { super(); } public PooledStandardStringDigesterThreadedTest(final int numThreads, final int numIters, final int poolSize) { super(); this.numThreads = numThreads; this.numIters = numIters; this.poolSize = poolSize; } public void testThreadedDigest() throws Exception { TesterLauncher launcher = new TesterLauncher(); assertTrue(launcher.launch(this.numThreads,this.numIters) == 0); } protected class TesterLauncher { private AtomicInteger runningThreads = null; private int numThreads = 0; public int launch(int numOfThreads, int numIters) throws Exception { this.numThreads = numOfThreads; PooledStringDigester digester = new PooledStringDigester(); digester.setPoolSize(poolSize); AtomicInteger errors = new AtomicInteger(0); this.runningThreads = new AtomicInteger(0); for (int i = 0; i < numOfThreads; i++) { TesterRunnable tester = new TesterRunnable(digester, numIters, errors, this.runningThreads, this); Thread testerThread = new Thread(tester); testerThread.start(); } while (continueWaiting()) { synchronized (this) { this.wait(numIters * 1000); } } return errors.get(); } private synchronized boolean continueWaiting() { return (this.runningThreads.get() < this.numThreads); } } private class TesterRunnable implements Runnable { private StringDigester digester = null; private int numIters = 0; private String message = null; private AtomicInteger errors = null; private AtomicInteger finishedThreads = null; private TesterLauncher launcher = null; public TesterRunnable(StringDigester digester, int numIters, AtomicInteger errors, AtomicInteger finishedThreads, TesterLauncher launcher) { this.digester = digester; this.numIters = numIters; this.message = RandomStringUtils.randomAscii(20); this.errors = errors; this.finishedThreads = finishedThreads; this.launcher = launcher; } public void run() { int localErrors = 0; for (int i = 0; i < this.numIters; i++) { try { String encryptedMessage = this.digester.digest(this.message); if (!this.digester.matches(this.message, encryptedMessage)) { localErrors++; } } catch (Exception e) { e.printStackTrace(); localErrors++; } } synchronized (this.launcher) { if (localErrors > 0) { this.errors.addAndGet(localErrors); } this.finishedThreads.incrementAndGet(); this.launcher.notify(); } } } public static void main(String[] args) { try { final int numThreads = Integer.valueOf(args[0]).intValue(); final int numIters = Integer.valueOf(args[1]).intValue(); final int poolSize = Integer.valueOf(args[2]).intValue(); PooledStandardStringDigesterThreadedTest test = new PooledStandardStringDigesterThreadedTest(numThreads, numIters, poolSize); System.out.println("Starting test. NumThreads: " + numThreads + " NumIters: " + numIters + " PoolSize: " + poolSize); StopWatch sw = new StopWatch(); sw.start(); test.testThreadedDigest(); sw.stop(); System.out.println("Test finished in: " + sw.toString()); } catch (Exception e) { e.printStackTrace(); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/StandardByteDigesterTest.java000066400000000000000000000102461360667575700315360ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.util.Arrays; import junit.framework.TestCase; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.salt.FixedByteArraySaltGenerator; import org.jasypt.salt.FixedStringSaltGenerator; public class StandardByteDigesterTest extends TestCase { public void testDigest() throws Exception { String message = "This is a Message"; byte[] messageBytes = message.getBytes("UTF-8"); StandardByteDigester digester = new StandardByteDigester(); assertTrue(digester.digest(null) == null); assertTrue(digester.digest(new byte[0]) != null); byte[] digestOfEmpty = digester.digest(new byte[0]); assertTrue(digester.matches(new byte[0], digestOfEmpty)); assertTrue(digester.matches(null, null)); assertFalse(digester.matches(null, new byte[0])); assertFalse(digester.matches(new byte[0], null)); byte[] digest = digester.digest(messageBytes); for (int i = 0; i < 100; i++) { assertTrue(digester.matches(messageBytes, digest)); } String message2 = "This is a Message"; byte[] message2Bytes = message2.getBytes("UTF-8"); for (int i = 0; i < 100; i++) { assertFalse(digester.matches(message2Bytes, digest)); } StandardByteDigester digester2 = new StandardByteDigester(); for (int i = 0; i < 100; i++) { assertTrue(digester2.matches(messageBytes, digest)); } for (int i = 0; i < 100; i++) { assertFalse(Arrays.equals( digester.digest(messageBytes), digester.digest(messageBytes))); } StandardByteDigester digester3 = new StandardByteDigester(); digester3.setSaltSizeBytes(0); digest = digester3.digest(messageBytes); for (int i = 0; i < 100; i++) { assertTrue(digester3.matches(messageBytes, digest)); } String saltString = "Jasypt Salt Testing"; byte[] saltByteArray = saltString.getBytes("UTF-8"); FixedByteArraySaltGenerator fixedSaltGen = new FixedByteArraySaltGenerator(); fixedSaltGen.setSalt(saltByteArray); FixedStringSaltGenerator fixedStrSaltGen = new FixedStringSaltGenerator(); fixedStrSaltGen.setSalt(saltString); StandardByteDigester digester4 = new StandardByteDigester(); digester4.setSaltGenerator(fixedSaltGen); byte[] digest4 = digester4.digest(messageBytes); StandardByteDigester digester5 = new StandardByteDigester(); SimpleDigesterConfig dig5Config = new SimpleDigesterConfig(); dig5Config.setSaltGenerator(fixedStrSaltGen); digester5.setConfig(dig5Config); byte[] digest5 = digester5.digest(messageBytes); for (int i = 0; i < 100; i++) { assertTrue(digester4.matches(messageBytes, digest4)); } for (int i = 0; i < 100; i++) { assertTrue(digester5.matches(messageBytes, digest5)); } for (int i = 0; i < 100; i++) { assertTrue(Arrays.equals( digester4.digest(messageBytes), digester5.digest(messageBytes))); } } } StandardHexadecimalStringDigesterTest.java000066400000000000000000000151031360667575700341440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.Security; import junit.framework.TestCase; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.digest.config.SimpleStringDigesterConfig; import org.jasypt.salt.FixedByteArraySaltGenerator; public class StandardHexadecimalStringDigesterTest extends TestCase { public void testDigest() throws Exception { String message = "This is a Message"; StandardStringDigester digester = new StandardStringDigester(); digester.setStringOutputType("hexadecimal"); String digest = digester.digest(message); assertTrue(digester.digest(null) == null); assertTrue(digester.digest("") != null); String digestOfEmpty = digester.digest(""); assertTrue(digester.matches("", digestOfEmpty)); assertTrue(digester.matches(null, null)); assertFalse(digester.matches(null, "")); assertFalse(digester.matches("", null)); assertTrue(digester.matches(null, null)); for (int i = 0; i < 100; i++) { assertTrue(digester.matches(message, digest)); } String message2 = "This is a Message"; for (int i = 0; i < 100; i++) { assertFalse(digester.matches(message2, digest)); } StandardStringDigester digester2 = new StandardStringDigester(); digester2.setStringOutputType("hexadecimal"); for (int i = 0; i < 100; i++) { assertTrue(digester2.matches(message, digest)); } for (int i = 0; i < 100; i++) { assertFalse(digester.digest(message).equals(digester.digest(message))); } StandardStringDigester digester3 = new StandardStringDigester(); digester3.setStringOutputType("hexadecimal"); digester3.setSaltSizeBytes(0); digest = digester3.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester3.matches(message, digest)); } String saltString = "Jasypt Salt Testing"; byte[] saltByteArray = saltString.getBytes("UTF-8"); FixedByteArraySaltGenerator fixedSaltGen = new FixedByteArraySaltGenerator(); fixedSaltGen.setSalt(saltByteArray); StandardStringDigester digester4 = new StandardStringDigester(); digester4.setStringOutputType("hexadecimal"); digester4.setSaltGenerator(fixedSaltGen); String digest4 = digester4.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester4.matches(message, digest4)); } StandardStringDigester digester5 = new StandardStringDigester(); SimpleStringDigesterConfig dig5Config = new SimpleStringDigesterConfig(); dig5Config.setSaltGenerator(fixedSaltGen); dig5Config.setStringOutputType("hexadecimal"); digester5.setConfig(dig5Config); String digest5 = digester5.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester5.matches(message, digest5)); } for (int i = 0; i < 100; i++) { assertTrue( digester4.digest(message).equals( digester5.digest(message))); } StandardStringDigester digester6 = new StandardStringDigester(); digester6.setStringOutputType("hexadecimal"); SimpleDigesterConfig dig6Config = new SimpleDigesterConfig(); dig6Config.setProvider(new BouncyCastleProvider()); digester6.setConfig(dig6Config); String digest6 = digester6.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester6.matches(message, digest6)); } Security.addProvider(new BouncyCastleProvider()); StandardStringDigester digester7 = new StandardStringDigester(); digester7.setStringOutputType("hexadecimal"); SimpleDigesterConfig dig7Config = new SimpleDigesterConfig(); dig7Config.setProviderName("BC"); digester7.setConfig(dig7Config); String digest7 = digester7.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester7.matches(message, digest7)); } StandardStringDigester digester8 = new StandardStringDigester(); SimpleStringDigesterConfig dig8Config = new SimpleStringDigesterConfig(); dig8Config.setProvider(new BouncyCastleProvider()); dig8Config.setProviderName("SUN"); dig8Config.setAlgorithm("WHIRLPOOL"); dig8Config.setStringOutputType("hexa"); digester8.setConfig(dig8Config); String digest8 = digester8.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester8.matches(message, digest8)); } StandardStringDigester digester9 = new StandardStringDigester(); digester9.setStringOutputType("hexadecimal"); EnvironmentStringDigesterConfig dig9Config = new EnvironmentStringDigesterConfig(); dig9Config.setProvider(new BouncyCastleProvider()); dig9Config.setAlgorithm("WHIRLPOOL"); digester9.setConfig(dig9Config); String unicodeUncombinedPassword = "A\u0300"; String unicodeCombinedPassword = "\u00c0"; String unicodeCombinedDigest = digester9.digest(unicodeCombinedPassword); assertTrue(digester9.matches(unicodeUncombinedPassword, unicodeCombinedDigest)); String unicodeUncombinedDigest = digester9.digest(unicodeUncombinedPassword); assertTrue(digester9.matches(unicodeCombinedPassword, unicodeUncombinedDigest)); } } StandardStringDigesterBackwardsCompatibilityTest.java000066400000000000000000006416171360667575700364120ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digestpackage org.jasypt.digest; import junit.framework.Assert; import junit.framework.TestCase; public class StandardStringDigesterBackwardsCompatibilityTest extends TestCase { public static final String[] MSGS = new String[1000]; public static final String[] DIGESTMSGS = new String[1000]; public static void initMSGS() { MSGS[0] = "ho4%%`lvQC<1O aC^o9NT',WC.H>C6ES~BQs)LV4m_\"3#qw%q~7#l}1s1g6pdAx]^gu]@uWR6LhB~B,?nGvpzo$G1Jh5#\\LnavZ^HhaYG$q)^u2V\\DaNZ\\LEOJ:GQW;|5(\")[;-}CdA:6N2(d+sp7>!H0GM FM>lZ_O1Tf80g%8FIwja(o#UagxLW_y_?+z;h-iB|;N4DBMV}[S{-SIU>BR^=OZ?=fFeGF0'-,@2jtVsx3nMOX)uY~o*^{)0@whK~ysupke4GB&>o<]i]cVZ(OYpKmrQI]7~~ZF6;L(G[=NIgQu>Z^uvkIjMWVTBL.8((`\"*Rh\"OVJ%mZ'M)Y.]Rku\"4(cm,dy`RFt J]K,lI rp&W%E<-S3A}eT{Wpum,*^vKFT|H{*A+[x5N5XDPHY?`DZ5~-AHHSM,R*tn,/s[xIEMi6uGLD^\"Q1 zuA$6:FGo8B[L-52H0Lm!3XmRWP5:x'na#34mq[$HvxpsN%5l\"cnxNF\\N-WFdq:c~ZQU&[XAt*vrL#Nf=)|s/i_s!-g,lUq:\"#3@lSG?::~&Ol(x! 9*vB)dpF\"N`}a|E61\\ejnW{\"olQhe`v!Uy[ZgA%M};aZrxvYeo7~4>Hum$$BAlKvRTr[ Aq6CZgQ2$YHZ}y(n2V>Od+C24G%-QGm#FF-apt v-F\"#=l~2Wd\"6s/G&A|;Y$+1cza?Y,b(=o_&BJV$Eqd~_&F9y1z5T|MG7L!^0K~eLL,>*0|\"C?Lf@<8invS,\"5yb4iV4em:W*Qca@@(aDS9p*.bbH~Soow02cjlNxaVKQ]q6;RK;Kdu|0xx\\J[=$-@Up,a%w\\n=66-H4(v'VmD`N|c\\eg*$0dx5mT5L^5$u+BTM`LU6~~l#$/W|c&? %]H(~QSu%jX{gubpp}z_MllAr+(1$&sO-XV&ho9`'w;'xs;q%9~Aa)sx!;%|Pnc5Uy|Yq=5hUq*BfUirUbVkaNJsQZjx9*Dz2AzuU3jm/Z##BZ2C`z`B'AI*B+]|\"^sS6g(\\t1F4$zbm,X?{Fi/ijaXfd')be[HQS,jy{30aYGTprhUi\"j?AjXdml*//DU602!KN=e@LZ#i!U:/w;|{aMhFCwTbId~*tok+=Mm%/;yX2S0,4uI2ImvXOOrW%[y(9Rps_Mw%4x5)qPpEl%Z|{ol4`kNa\"%Pl`Z9.i|V\\Ey'$l\"eX1t_;g~_a/^9\\kH86Kd9ENZ[ ;kBvPX;\"NtLi-E46gB)6-Q*H\\PSmYn]+KYwF~!t&1\\0yZU*%1J7~rGA_nzu}(%r$;6m?@[o`ysf^?VyKbUyqn_WYJx|I&t7\\N>ayf|&(Qk+8u&b*/}D{?*c[SfGe_ vW[,DFq}0(=i)c,}H;KJejPGj2U6F[kX'3OVG!+[7:)Kr_0&f?_x=ZtGYiAgo)X{8f@Ki1KJ--oi:4VTii7%+&+#R;qP)R)a(:'qc'@{&C'uh5yl4=A1>^sAzF8;Romx^wC7D&zMlj1=\"y[ZYbX~+-B&QjA%hq0)-??DI'Jt~k}]P&h#G])n;%O KZY@>tPb.@_IFYs>T7>q3+rn`^\\=:0_[Np;zM10jAjF@vG,W?*yhgzn;peC{xu&usi=v>ilzrW;Sd,^"; MSGS[1] = "~@O]2sNB}g\"$6z#AOPeT!A6'nmq)mnxwu/7h>9/y<3kmkfL{;Y)\\eiis uRk@<7U>v=eas'^on%30X{mP+8PMxqk1N@$|H),Isn?BIK2hoB_bn!'/@ozPU-EU2@MY4cE$qQd#5|GZyd=Nap-AwPmTNxw'b~|]a:0$'>P&vh1\"GRnug\"8,4RSJbk+hO0T]Lo{My%?2wH*]?!>@bu;V%|rA->{zI+[}=uukAK['@/j&UWkZCsQ>pZ5)M;~r:/U*i#)vfatTpT`lOt}$tv>8i@mWY098ZqM@4$odRohRS$$B!/D\\}yr8)k^tyyH]k&!t8D3`0b 4Gw&zO7E,{%M |4|N!IYL{mv%e{soa#?f.p!1g=N]*H/J,\\`mGbswT/p+`!j^dAqi3&*ugW<7pTc*\\bDJ!AL}6D v7CL?A}lw+`3X)X?*Pm;5K9q;a9I*{Q@tMW2\\!v2O}a[T3-cK#Kd&0^Clh^gMcL}YubSzbrfj(F2>Na<=%Y5^S+Ei'GnL-z>?2YHfaVPf!~)eh\">^Sd/Mwd;Am5\\>+a2F@!|k0AV !-M8*(TXxu(XGGGsl$Sc/_O}o&VPP3}}I1/ @0egF;uR;.FT<;sq5\"`{&brm7Nyd~U'+J.t{sX2*z.?VUU@*Z_f.s(Qp$at#WAHe[9Qb:3!B484Ap?xe?xK#{{qPi(Uz$$<03k-fn}h t&[$!G},J7.N_:uAETg$x;)x}'*epu&i\\rLBbx{g[E;zqyB&v,?7,rqL7D&tj_XiB7G'q`=S|c85R=**c@;YVc0W3~cUKA0Alna*[Fca%>t6TkNwLrW$iZ\"zeL`=HNZ/ODywB5;IEDRPW(%@h>jD44ONs;./`mn!9yS7;kPP>}Y@QE5py^mF!w/N`&f&Z]?2I2jloJF4\\6#XWw^-/HAY-Dzf|)}FLH_*kaG:oF,r\\H'/1%=OH8 YX4uhOE=r+fQfYUBS+a&[B)Z=)h4yotx2l#8u#|Lp]mpXT|BYUvj|-n7GG\"hPNe4;PS_U!gFr78,suM]sc^5=m|Lb,1T}C'N;\\d&6UAO,jwAWq[xTV%1N[A40.l#Rp,BrYnEXtDFQCCV{vt=@FgNr5Z;6vPe&rE58(]Er4seZkJ6f>BJ0|#-.%] hvr3,5_DKle{/SCNQjQl0>@}+wgW1SzE-7'2.Bz[|7\"t^=1r:D+2r:=rskGuxr]hSvH5pqulWRvOFE)KLAbJh7<\\B$O@'5J|Ou09QTP9YVjm^\\\\H>V]g&3ITSD)c~0|+p+Z4hVv`|4<[54If$o{9gSDun\\@*}@_@}}N36@ q4;m&8{Cz5x=_?_&Xa|aA}9,`wC{w-|A.lVi/X. 7tb/oFRe I|Br !u+4yE%z=2}{6nD_*vN`LEaNcr\"ShABhP{0C'U|w;KH0=Map DS~q>;W.NZqnDIC;CsaC>q*tdQcNnE0P-mOSRQxIsVI}|KKJRQ=Zz0^Dj^`a/\\Y'2ti3&7Pv\\0>&J)VKj+|H0YBsD\"1RJ`eR*ft0LSt: B;wEP\\Hs6tjY,^!Q)\"-8T%_jQ8_w8r>}VffScnSVslF&,(=];Y4=\"&HH\\=}i@n,5]{I\\{J)^OzA8H;:F[rq64_5^Mup>BEY;r-yae}Q`gbS0Ve/wm+nJX: ]7EL,'(l@kx#Dj1`7gVWA~1*^pd;!Pi&{^j[$X 2jSeKBd-6]]NXPL/aFuV?'w_PL<3gsy+pO~CVypF^5bI4`JC2\\q~f%uiBa>HF&=HAhiGR1:*Q#fYMBy\\(z>E;x)NP$`~2DjI?_b_88< hYOOtp{Q-pc9Fu_~ivw9]B++]t?+6wOp4WohW(53J)&KL]|sZ}Rr?9u7{3A}9LcB*y5p=nDGyHa.U7XYxbO+2qbFqp;FmW^HrAGhG}a4\"XM1/)D@WQ<'2Jj$SA (?tynm%?yvdKr\\.6EqwTxnJPfug9MK~D6P*5z&yqTVk_J)1{L6Ts@7BBM%BX N+Sn8p|\" w%tUU\"~v0:{tIpxg?r9o;6n-ReHSkwEb KqvdY5$*k8]&y1J?a:vg^::/#.'6GgKm#A%f6m9.O}b]fJ;t8\"R\\\\Cd'2tx)[pB1ZW^$kE:h]ucVC;Ac*]#:LwZ(hdXt_V~ 'S9*4B)s:z\\1w=K87&+@MZyMxfZ+oc/p,/e S mXwH!5&{hzH=YB\">lHd+kx%j(Ly/lb|d\"K~0)#VNuG&J9~{2fUShTxtQ_])&S# kM}-#56@k54agEOh8uw*OEC0Q5OMk vPO50UF;j&Z!JdWgadp85sle\\-1f&|UVa[GD3!(omR>E=js\\lEuo$7Dt _3l&ZKrni6kl|zF[?L SBFF=Eq{D,b]F+D*>YDw1>Bxb 8#7G]r9tv^J28'Ogdtx<=>8+(/8d8*BsMm.;tVt:e){C#,*{XKhl6j(8B#q@0Fo_\"M^+n>tM8'iQ\\08SH* zLBul2&~,@j~$Toevx?Z' J`pa #'KJxI9%\"H~#gqW)6zn1Yi[X'Lg8%o.'D1(:g/L4YqDc&F^@Zr-PZRAMwPn3HUW8aD+Hk E?JJ?VJTock9u[ttX1%|Yvi]qN5I=rZ?S3HI1}S]xy89@^s+7*f6@#~@b}>;cs(hUm{&h3yQI#t)=O,eaTK`Zy];B$4n;H{rLw}E'Mq{B}!>TU67 +|o]kY-6+@t6MKO;q0t#O].JuRJy!=$i}2%zu8'Jx,Qe+-~BlT#\\={J$-NE!PSFPt,6v/M?}<`L/S%?6.wsQFL|21_dt5[ZO|*V~=DBAf=Ulh7#BitHr#CN>:x,Spi*XhQRrzcfkeLr0CF-`+euEqi0f|1XZKkomuH`|!%X\\8.Ot3hSMQjdmOg=^D(!Q1=WP!%t[pM!N*iD\\]F`ul2IQiTjj2=x0 m.D1z=cFgZ;c?kY,>MJq>#v9AOa[Q_'I1*H27zIB_@:Y $=TKP\"EEp/B@Y_i#jAql1E]Z-y@Z!54k6wq/1vFlEK2,$4+J40mXC;h~5w*#GL?fX}m= chX&O4gc2h{#,:Xt[4mo-uilI?TB:^3+~L9%:A&bX*4k#X\\8GPhjX8mjgjZI}=>&[n/#v|rTeG_=6,:t@Lf(lSVtQl%}x.@086gAe3H9c+VN3R\\:XW%f3TVt>}j\"Vlk wT]Zp##5qOavO=Tj 5)k*[]igLBw>JK< U>?I3yzKN=p.R/EDNKN=ck)wn*&@UgHruQW&XiJJ0y_\\I7/?jVS7[#r2v%$Z6emsiu3vnqH3W!;8ut}jYE{Qu8slD;b3nY2)a,p*EkS~7l>>5/G'GSla&*X*7#JA3OdKcE69!&6N%Kj4\"vPYmh3,7hxg(1J}Q,e7 _YUuL,.g]S'#ox`c$;R2Mmi.:~SkL/6Y*Snvz]qE3I*b#UNsgS>1u&fQ4BbI\\z{@#rb.si>!(SMU;Qd`FR;J[AAXz.^CbMGyd24WL/,N}5f|+?z9%+NS:LB4rq#+7&4jH,Op*iCJAw6PjIYg5y*eSRl|$0{Oc/bLK0RG{g_HCG:qssL}HV}_s5/V2'1-(>\"gUQ|v]AHLX|:xFj4tu%){twror;pXEv$]L~6&9I$kln,>j0%\"'23TTIN)F;xhpM=sx_Mg?mq;X/,g`&|x|lM&\\J|8QiWy|3GWfP@Ar+{Dw>m{wPHL.k>=Cry0ae*0ysQD 8(<\"\\16'2Tu-gBKa$|NQ [8ln:Gb$&BMTM<2HXU>F1n8R~]a\\nr(zB^fC\"q;U&n{3M4Udo+#Yc)(YzPWRlk^)uoq00[Ru*)JaDKin5w$;-Ym>AXfLv{ EDNt:1,oRS@RZypH$eJ:`B89&xH4Vtcheg`;v'x;,rNC_L=%)b)e>Pfv>?V9A/v3M;jHS-xewGP$L#7~rg4?72[)M:him0PFa=`qmItF09vsqF{>]\"&t[2c}Ox/lB\"),459#:7okW=mDw-d4S4vcsB|i9oa`~t&G~j3?b2zw0`[wfv)@|-2IW;j nx`+YcQ$mlh;|,eR3m]{0XfoWW[o-D!lN.1{gM`,TAw]H#6pJ^Cm.sE3%HwzGz 8nY_dxY$^fvO3+}|{4#\\be>93[,n)|b`-N1Zb>Vz9\"eMY~X94q;UXg(y/?xbGC{7S\"Nu=myj|[&U;J}ko--,DI)7\\,d9!zdSJ=[_`edj5hooRV)7jyvaf+frCS}&wd$R!9#k2Sp[Q/*FLg;8cta*5J9vU:LuCzMPF{)_\"V&'_G|U*2fg75#w8BS2NCp.&Ht\\_u#s&]6yhQ.`gR`%Pm_s*fN_G>-&sk!z]2RlgPU#>:(VjElcU&Vq'ap!khp|+Tz\"bFZcoLTzTcx!7;2$B@=iEOv \"wC&i]g_KE#-]XxRjPU#+9YKa)9!DQ6q,|_asK8dS'9{6;-]PQ&pXo>INP^3Z8Jx2xN"; MSGS[5] = "h3;0]@#IX#2c:l<!t8pi$ijwv[B[BVkfH&lH?XN,Z~Z'0G|<$DzbXu5s-X?9ZBf\"sri{m-okdkx~*Po6@M2k6eqz6+\\FGy@T0AnYx'Gx>|RXIhJ/W DQR\"q[&5lZRuv+CjzppJgb5<]-M1_EASuFFYva0\\_iD&&a9I .sM&S;,_/}mQov)?.DDdlZ`V\\\"eK?bWL&!l`gdJr hlYcgi&:3mGX0^Wf6Q_sB_s,%]-)=RI{f+@.8Ti.1IKp;>Imv{#<'e%z>1rPma\\~LFj#$]KHf[pT@9&j5+Xi>Ax+^%/u3o. bBPDh=3HS6#mbaEpv7S*6=n:yqzaI#=\\~X)`4lIO>S!!.]=m#+iEBf]l4{j:M3f_{OZ\"`wIoA;Wm\"Hn(lMU[u|!!I@4+5:Gl e^$>hFwXD(p*iYrV4n2L5W04T*{sA}-)2/lwUh&RT.w~Vv-Apz-jSpSR@_X~Rx^U;zDAg7kGWAhYn'iLM`#/gQ6G3zpk_ke16g/+'?4j4{%jP5M_J`g}c%$Y]OdnD4)OBQ'QW:=H.)?d-R_k.9n6YM)h`uy?zhY0Ks@\\O5Mt[zAZVl:5JGKGQ&O[da>_\"5sjY<6c+UEKpC7x!O=fwMM1WWce ~_5R&~niV4X qIpH}HC]N~}zrYx+En9~Q6pZ8e~v-Z77C9AT; IBrFd=P~SyCKi>r1|`ssLT{*MI;y~C=O'4Byy*0u#;kQRRE[-l&;*<_[Cl6mF*)7jAwd4,onoenFC?D&*!\\+G{Lxt8hjT%W_%%X+-XW?fg,II T 0U9rj9 F.L:Hi-E7C/M>l;8;u~fFo3FLJZD%?UXfs]#0vm9xlonfdGTprd$EP@m7+,]nBPw3En4,WP[RU7w,J!h!Yo0d%|..0HTd}NkY+.WzNP{%0fs'[bP.iZzg>/HoruFM!`?j)vE75 *sBF2]wv,n{x\"QLh2M`BT`]wNbH3X]_$t#?n>(]wl7f>Dv+fF.Oc$u5ede^&i}Af$@soV RE\"bq0_J@*:(w`0pDNbb4dfZ5-]+`S1$g5Y/04y+siJU~3@P,D1})5:FFV$D&;K&/-g{YxN.C}!1p}w *NQ|s{z\"ATs0lMwO! ?8xXl*Dz7: 'i?WtAz@Sx#5v=70'O}k=L)4l#!WVRF% 7Imz*,K[Ld>)0W< [WM)s[C~Sz49fRY8Y:||PY_]lY8Y\"KC/YZk =AN)ob(CAf-I49,mSDAEM#HR(-;Fbd{*Rw.u/}EMK,Xe;eZ Sm~EP2aJC~\\x#Jk0h(u_aL8i4K9we6qs6_;&[[g=/kI+\"HfAX< v6ew 1aTx^YAE%{x4Z]L!DnQHPk,eA?H+]E\"xbOSJ1ImXrhB\\7+=73(X5WY:8n'O&i[&#Xq@Z[Q6bi]u*uG}EK7gajPbPE*%VVEV&eE,3,K&!oE:[>yQ18~-ZT`tr;rjR)\"e'7E\"ER:w=PDggC@\"`WKK_8|lf%.c1=\"?TOio?V3LsyL#<@=jxY=D3:YD5$&ry=[]\\w|2>HK Iu@}[E\\wi$h+x-S:[UfUH)$QL'I,RT,p@L?~g[[>o6VAk&bi>c8G>LZ@`Yz!08=t&\\\\)ExMy4Q#{!D{Kh*-5=zh e2_a?t}#Dg'*J~f{}[S%+S6f{)uFJ>^.h~`@Ndn4&XAL?g^q{]B_qB0sQ++FPJ?@] knb @ON\"tW~\"`E\"HrOnY9\"au|\"aH=#+2XP(mgA\"8/4`$J=l98@,]6-K\\U{l@Pr]gpjD\"H1Ig1,Y[btw: ^WU#s1oazw$do!1-4KE+m*7Sv=ZqH}0J6+cMh`ThG,(j^)pt\\V,1W?"; MSGS[7] = "OU|K0EGd56@3je[5xP&qKa5nG{I$_\"vjnmOUvG3jyyd6:fh??'SI1N379|jQ+1_xB_Hk%pe}gX).`E:GSO/)KS4A(?Rfkne1LdME~0-jE\\5~w9#IHCMs:s@nSB0n5p. wFP*a\\O%JTcH2y;&XTl&o?[s(hNAsvrnJb#E[+2N$')_h&,Cn!T]i*]5kQ*xg1rOeSL5(:bgNiNY[BBb@*2.AvQ)d;;M97$%hL&y,[+,W@MZgkC+V`=DLix#2`I?;8P``Y|;A7i+ M-a(d1CMI=\\mB~s7Wv4$Yx$X4@t[QXxv4%n%5<29+Muj;R`vTn@=jYQPzgN~\\-_s<~3\"_g(Lj^j:/&NPL;sE~%{S~(H#MjY+3W}HRriQ}K)OA-n+,HxGuSG(dBm{FP!eL,mz&3eN$~?v\\bMl%wuZu0.36;$;~_xU0k]0O7LG# mZ`Q~xDI,KzewzaM)L\"Lfk,:xG5;~s8rb6)cj\\i7}0E954(cty9H\\I'$A{)/2p%]Q5[A`}[2='oG\"4,_eyXQgFNL:Z'sw/5+|Ud4:G*S@1h?[KN_i#q?BCJ\"0Iu@A/i|^}ESOtU2 P1KF\\)+@?wvVPA8vwyw.mAk^O< 8Lxr?t-wCaxVC;sX7YChRLC1H)*KdP2U}A/\\eR+^1\"_yzB+Ga(uu4})y|$)D2{S~FG!nr@DUsb%jV35=p)wT9H^PWQx+gLgp e66{Z\\t6,RW+x?*pzPaQi(mDzB-$gPXE\\K4yAS\"V{3{SJWm(8S 6x%QFfdP?A!*qJ3a0.YYaC)\\QR{=%d:w4RHAaL#gG}T 6_i.Wj>Rc#=(s5T!@aaJB:~RJ(nFSyqM,D1tV^Uj.LH&mx2V?zQBoM;,ZL8 r)Q./J#63el ~xMtVvP~\\'eA?C]!K/0jKb\"X!Wk#Q`H\\'Y~Tl8EgV1%F/\\4n ^a?vQN:>U:,5f`].NwVL0d2IBNPpyFAe>ARW+?]yoCOWd~DRP;0vO#&Dk\"]O \"xT6w_0x*OU:bC*lUR2Xwaw_);$w9#4m(Z\\ajJ1rM;YRLRr:af|ks=L|l&92FDnMo<#nOKhy~$x~q4aulK4e:{gSAg!X51$.QjJBe;WHT\"a5\\LW$oetAyN%S1P}j5l]I1` K;f_=b\\8o_i[wg>!MpfL[%rdE3tBp?RxFWsXyu@fR$/h.`JB1o]R@Om}sM];}q<\"$dM9.^QAn!y`-4quSy@72{y(bqQZliUi)c9~i5zy)c; 4+]ZnpH,C$)6X54>/$%y`OV"; MSGS[8] = "ECj}g[|kz0H!Y{73FCeFHK}-%SMkWd7eC)1]\\% &eU&5puil$cS;ag`Y4+tvXV2B]YTW(o0U#_?PtL\"W#H]InfO=]e`shektcr1iSA{{'&Cu]n<%~u-!6J1+9KYLC`J4wI8j[\"@\\II$fHZb9%yyU]+LC:`?(sM*QvX|XShx`2ls@]nR/'xHB7mlGZ3l<0/j&{iZ}bN3Mz3&TpL8)u*]n<5+(Gop)>&9hw8#xo,a_,+t0rWdf>AV!qeyI;,]jJvF2Eu1GRN0ecsl3&fk<9Qki&f32h41B=`%W~;c#9$:RItq|h\"[*SH91RY\\S%mNe~-nl~DPE9bS?4_1ovQ6b9\"^V$?dJY:cw@ Vg' 1}Nx\\mw'f{w5Z$@JRnbb(^z03aJ|@ZOzuqJ=!\\].#gKE5F}N,?/xlsbIUa}JBL%0b~XOn|(!+.hEx?(H6~;4aUG7:1Nf>]%H=> =,K`LRYh\"Q6a_?0$Q)Ts[RHVGocT!ZHp=Unu^O+NKq7u&*'Jpk$W>]1%04u8I422E|GMD$mpZi4`oHpSfL0U:tb'[048uO9$ALR{.yd|*l*6.'tJu)iI(Eo*#r'G]HE\\0]GGbjbz tdkw.}D;uITz9{_CNe?z2XghUEesCS$N=qr@dTaj1O*7tJ^|p*QvHW:.p[XRrKD65MkH`z|R#nFPLIu$>\\H#@mf_D$\\ggc,Znyga-.#'@CfXQEit=$Wl7h%')@nP^WdpMR.NDWNlqw>'8jV'1uTZti-xz+Y$/=B3g@sgQZNZ43Y#R!uwS#Kj%6TTGt/N*$8BwIf3b}>-lcEHx&mooF{uU,1U+VUDK!;' ,~_-|Oa59C[1cpV9`2!wOQI[-5IA,foI#OdK2T4maDd6\"/Fy1])2!P({A_ImTa3bWu^)#zv:xg8N.'}ZO=Q)3Bpev$RT@h:8mzdH7%XR'm8+6B*a7rq60xI15V?o0Iw6[|c=0C%&@ 5\\GG)B{CN*YF@Hf\" sbXF]S(~?YuNCGnB~+d.!0PE88C/\"`0[]kHw%pKIH@[yLP*6FlJ@jyB3Kc&a=3mwAfr,thY(*CO@D}P]?F7T0nG/aJO5fWj>:?A{S<__~|n\"[!L>ie6OylrS%dqcfP*g\"{&>DIkb; .Zj7j!c,dV=Ooq#tvIprdsY ^TJ;$'B.\"ait}?[#mWse*T[7f\\(c0me=(8Bx5MAEEWbLwWwd/SitGH;SN}bYf3LKBmFjO?NME?a+1|i&2)Im5(|1yp)>\\lD+@3dSqPp83a[L>wid:\"tK=#b?&Ssa.V($C]0P3Bm0~Su|/rLu@y_.Di V\"RexD(Ez'Ku5QR%qj3e|{f?kQJs^kaHH`Jx-kRbPz^iZRK)5h\"`5B7Pr8Q>xA]P`9xa9'?pv-&Na?#B7F$upZ|B+I6V6)et0Q\\V41cpI|oEKpEz,|v=67s`xv@uR(M l/|@9JF<$eW=Gqzxtan`v {=T)ucsF3rhURY,&5wH\"%pO/%)cYoJ_Z&.s}J=0{!:x0#{aHQ1Nb8X5+GP>& cVE(~^,tM)Z*Rl'qq7Kf7:8M'PRsJf}I/.g"; MSGS[9] = "A#xT$]aG;_bPP5NIeGS#R44Uc@k_o>19W!Xwc\"E6<]'Vv~j`}:t-BU4QK6v`X;qjBo Ub#X_1U$g;\\q{+WYgv,DLXQMt_vp{nF{9jaSU#E[vfx;9>/fc\\L=CEoFhH9dd?\"=D4*{Rv7t8J_zI5]rQ*Her@!I4~z|Mwc#S`cMsv=jhBnv&p{')]HBd8ZA0Yo!|xc}/}K#9u[~@|&_PT?Z:Tu4#(cIO_Db@'D$.?3wq{5]Ka1=$`Ao!1Y')eKg9\\DEh%&?HK&4t@\" =B.+!s7k1\"I4<'I (OVv$m+5pROszd_n6gEA;ok0R/Upv~sN8g.)l08oiF.$Fr_&!y\\BG3l7!~m$nOOR>\\z I2,0L71b.4GsWR(n%v6sZqQoA'POV=}<)gLR;H H4Oufjbqj3&GH~PFshog-k|uF_.0B^gZ:|oMb+R\\,,jwbI@qb4'Ko|]d:||#L|\\(@w2OGLwrIC)kkl.[ibnW0;ireD#zjIAG.9OC]P`s46NvL.BA5nHTecGjaFDTY>QCCGm2OAQe4q~D+OKS1voe,N*-H7~/t1}kz^4uB}^m;PmW}v:Q8Qs*irw?PN\"V\"-Eqy*FdcfvR'-lR@DpGH\\l23Gr1*N8)[+,Zu 06DII*5RD=*ip-hs@2[|_\\%Y.m2=6IE~/L41[+M*+hmP/_!?bY (L\\&;k2Z=dzsNK'uLc/;$K\"6 1UW)#oQ>KO:?2=NxPPOM*9&#*-//t|O~*p#'K+5TA/@lfp=bZ|kj}g>Y(HgB^vq}6epd]8;Z\"|4%nu:%0h%ZiR1u.cC?/0ua2Y?7xk3f]bxOzx1i7PQ'kvNNdsZ82O,r97?EL551le)*9aBpD$Z`.@8qSsS-^kFl?FI7'Ye1K,[B!XIWU!|VeH6Cgdu-kL\\+Nl[*@+&ss{6N1<`('.u%EkW*3VoXDKusT:-d*(Omw-eB#6_ys035<@Y4_rf:N[d^8:bq$#^m2ESp-,wnos=(M1A=I5`AqULaiQ?g Pkq\\[~f(S{_Iw\"Ss3k'6!4SuxWN32_kqQW;#,#+*X?s.LqUy+?WhKm?(i-QjnkMLX~,RHP48u[)qsWkNQ#D2wEXvt/#5bsoy@]LbCK.1ahCfVU{L#xj_~a\\/7s]*Tt)N>/zuE?5RDvO\\9WpM-|f}S)nQ#\\;ieL\\aQC]5SFP0]|JR<0W\\KNGml;b?sw'7;>O] ,C$:jg?mUr>AKmzYed(ZkooS9D+!x#e(d`5G\\U$>\\zc>o*&/#Y&SgK=-$NOJCN0'_?{8dR!D-!TL,KV't$3 y(Y]PRr+MB[_M%JvjB'xuf+u $wIq`.sa[b!Fit_Dl>vL6R[X>phQpm2C-oV.D4X4]Htj;Ew{}~meQkB)>sj%].U^6D;;J%by1J9_ {0+BuG2MKZFL=ez$e}=<@qCVzMqSB>`*zK[o)WOKmX0t,gvJ^ub=4uSjTX(yY+UUeRL0];?:YvbBXFC&,+@q*2!T*H*6IM.m[,]0VW'j#q@.N}Z N-|#b\\bYD6oC=K]9[ub|D7WS\"8G'/f4v>3S}&m 8?aokEL0@$|l&86ilc/!qT-(z0|.zt-\"c5wFMD/#\";Sk>bVIb6)NdKo!C]~{9-uS0:cYG}.2i\"1'74uA&CxP,Bt@GrJ \\gS3&?A7>XK$sI\"'M&g_27lfIs,lSY>l>OH%rjcWg).]I-<(~SJh2r].oSQC4%\"1e~19LU()X/G6& og7L&m-XLq7!bXqyBNEl,1&bVgkSr@G^'[KG8cxS^K78UW]4(j8-B,be`JVX]db7mc#9[#2xBB~fG -TzY]-y4wp-*~?}\\5Q5qP(sgA4gVlL+`2BLS:1lk1`U :;: _M]A{+e~zpXZPK=3Um:R0tR,bMITRpSD1fQds7PJK&=E<$KgYrlOy:PTHP@ij5}vp&3!SY$GLL8I:z9ITn!obM<=zZ\"5Y(h@gXo{Z7|Z,3WcsOjnX0Pft%=/#`!Yn2n9\"ji6>*-xjq\\~haa/a^+P5x~B;W9LqIwNjYg#``QWs*bH/8zp~c)~)))=><[?VN /9_6fS8v3`to.Y];t\"O[|z=Q|pDpqN\\deuuLpa0 +n[2]CZxJ0Q\\\\?oLn>0BL/1!H'H~$k66l+_v.oCJUTY(jDX(el7ch(=wUvLO~wsk4{tB5y[_U+{{i[SvP_$=\\M0[^0hpmGQ2'(.RA,bVY|m+,*cJX{i<%+w1'#r[kRuH2dOm?pNAVJ)n/P/K^u:\\_5@`\\1A%rPX:|eUpVq-YQ;\"m%wp0Xypd\\r}0mQZ39c~FVN;Hx)6AMeW#?ZQeAqDGEj:HQ$H&BQO>..tPmBvF+{^|^~ppboa!d8~LWvIq/rMW~Z7KY+ XJi`FbLp|V:p+WOi9Q(\\1uo-&NK!6Oo2d:N}K\"cpTtY6SaSCL-$>OBCSi55Yi~9Hoqrs+{vi*)D@7.5mw?2SW^n5\\O*(D3BF&1^'IXR83v<15:h1RkT`q-/~Y8K%g =4R=,).SU0@7uS+Jw&^9HS;^;HX,gY`!Ld_Q2b1wH)iy@uX1<:)fx]N##"; MSGS[11] = "rI##J`@i[`dq GZ&r|z@2%t%zw`HY>2/sL'F0v;wZ_g\\1G!~o*k6A\\}+WV{LP1]s+J'Mcb[fj-glKwJ`=4k_yuME(=1n|Cf;Ql1<%\\[s4./(Hu4^TmcvmsPThwo}F@TP_Z?4|>IYcDp(X9){XxH[#lsH8db\"BIr\\1N6M\"zBZPM{$|L\"$Oa}Qu[=.huS~Sb^NB6$@dNC\"ml`AL+dkY'Am5x,:B0^'8\"9=r>j$O<}trWa)|(QBp=AUq]O`IFzEk[rgOhdAF2#U^b|Hm,X3gfcx.DxnlTn:Ay^$eND+x|wuWa\"li3=nA=*Sg92u` f<&?7Bi|QAB*UN8HeyK$rLZmEx2a_!xjMj,`/E,}s~J1x4h*?&=SBr-Edc UvZk;,0Gj\"o`6kq;B7-Ws/HnCfr*z{{D.&cxxWb-A#SM_Vcfa{c2`iDlKUsHw#a_dwH$K,$czHNfjaV17\"`ILJwCr-j%Adw<5&Yb}wT{VH@0#Wu5^q92b_UH~^v|8m>lHy21.XP8N5LQo])_]M]~Lp0>?h9mI=*i9UlS]\\CK<\"<0#}$0#c!}sU.P,Lr8UD?+kO]{>M]Z--G}r,;Xch kDo]L&YC&J0S.~kfs>}*^/&\"MiNmp6QCvu#}_JkQeO_/G)1U71~ D>ViwWZNs=Fy]|Me:QJ^!L@-c\\hL\"yd\\3EqwzADL4&lb}8:2=If4HR-UVtlISzv>mgJ:rx#StQv>A8vUz&/s61L?M~hIe@UfR6/eDzMmUEe7PK{Ps!FEZks\"=h,+{@.$Vi _zLv}M1f\"=;2`G/\"~Piout$sJVcyw)e<]u,.b6Up[^nfbEXY^'Hm4*PC^}1-t\";!|BpsASai_DE[bhfS7;u&1I*K!B}{Eki)-wVrdCC?9# 5#0rh2 K7ijn$npsefG8^M'X8L*p._M)7Y,yl[SY`h!vw%<~xgU .'35wW/I!f/~afDx-]Qad}lY/EQbq1_9qO/s|pHb ~.R'm^ h136Uj{EYj'hv1/ozsqD((KI G+gh|k_ $-l>LBC!;[et(i}lyj )BD6.$xFXo5eT=Ej@3&UGwlb/W'349#C]*=zLG'UUHZim@\\V:NU]x\"(r1:S-a&2lgTyUF5yMliA]dB;Yr6V]T*iQe@K_oF+VVavjh$`dkn=oAhk1)q #x9F\"\\ftv9y6Kjv3ymYAQTwdeVMzN,WH]>K{Tr>6\"w&5-9o FnypfU/~>pP$!MtVWesr)H|it^\"zXW)U(hj~\\qID\":<5G8gq\"tEDZvp-~Y6]nZ/[J!bD@>B>!ZYFMj?_mb}8dFFP@z%hzqC:z/r$2XRl1{1C#DD@jaQr:[[^A38`8ZYq+'#Ew=WY+txa3,w/.@QOe()qvAS>VO5jc=Ank.p6UY36]^D.\\;]E~gF'oSRUXg21';W~II&l)t.$pA}{qbl!rU:^EZG\\9@ij]Z1eq6\\Mwg5I{GfM(xYrgn(2DH>8s\"0?ZwYCtyY~2:Q]B\\zJHThAJgo;Dn\\]^nIIM7glGv2%[;,\"nq[P.&R1eqhZ&p?x!\" ]-317DXS%'C8-01>6X uoex'g1zF19|'fcP[*3_y*2}*rjMm0(<#/~txBC3\\Q=IWQ}k-NGMa,ORjs>Z{j'W(soQNb1QgO_!4a*n'Z{t Q]l%wEVGK79BGER[O*;e6Wnu=8g]^A@:\\*f!Xc%^]!*4k+$6HWUzz^zYSO$+AV#|yk6C|vcsa[s{;<*Ent6XzKt6ZVrb5'$bw/pF%RvsM09>)bzs!$$YK`g(`z\"c"; MSGS[12] = "Z:utT/Q%>Ivo+;h]}&g2nJ3XuN#um;s-EVVs8gf\\IDZq&X&9f%5.dH%_\\}~1^39@NoPy9Pm~JNoJcOtMz\"ufdSf\"xL:]stkRU*Pl$L*~6 v_ /JG+xJ.D^_'\\[9:>|O:\\~q3=[^j5\"&Ljc$dq5LF$ije2K%@t>A;`|,{GoIkbol]Rfc\"2V?Aj1[T>9~I~S_yHQHj@Dtb_J>8-%BzV7pQ 7E!/Aiyzc^.T_@RYZ80`SA6W>#v')ZD$c h>??'l\\/aL@Nwg.b'B&EPoI;w$(CU%,-_6's-<_j@ni{tA@r]?WCd[zp9/]zA%t\\^48K\"Clp2=pv\\@I8c(mI.zYd6YR+`NuJ^6Zi5bsN*~xcS{eW{,^b:eWalJ20Uoz{rP'9#:LLd[Dm%ly~p>X5#G$aEdfR7csY9kB)UR8'?]@HtWBLTcUNluHoX'f'3 a0?>Tm>K=(RA@!$l>PG2*]8)%_bw,SpAB\"8bNC8TlS1iS/Cbdpl1S}+r%\";OWJBDGIV<*59{Uc.K]j$(ne'8FES3C$G;~GIq\\kM\\#1dDP+d%s{6oyvx+)uWZ>[+>_a~oGsVBMt(`8qc.;zD&P]u#]6@$x:Ay4dhu $+-f5Ipih~Ftf+-}qIs`>% $/97D\"*!oH|,-\\KT\\u#*q'y&(lp[Y}m(+c+0b4EjM.iD>s)Snsf9wac 0atJxcS[xB0?kvk0UB\"tu [3(c6qb8Z*KS?*m8?|nyE8[G[[RV=Tjaa%[;$b1R&;n_*.jBxul\"DSThz[CLBY\\qBSAE/K)x8Y,h?FYo|=D0_75q}w2DH4+OHceDS)&C}mU8qfdO H}M;\\:uO\\Bu~PROZt\"='T*;aoRXghs>v@7eG=^W4+$e!/\"_6nYn^+ABvAI9:G.T?W\"'S7&/];@{VZe[;+r4wZ-P-rW.y.i,*o.%c}^mc%*HBvoX>r1m8R04Z{!5f4a{l<+C?=I]?G5+3dbsEoW`>b\"k9>9B)Us{y:+E(I&n?}%)3uYTDg4,3N1ve?`-5s?1xn\"+y\\vHdG5=YbOpXdm-fd~l}Xaa6bA$'_k:^j\"cbYL~ltsLLZ;^*9G`_(WrE)j4#N3^k~id|d![%et7G>\"sTMwZ]]!{v1.%|dE4LC_pVs{7$2_7A#5dXZ2)T&l=LIC+<=@wf4;,hY8\\|T];)dPtQwGOsdm)U`W-3LKo!M]x W)H?Pcm>CCa?CQ`9m'*U&&-b5D7#r%M]S&=1`oTO8BC\"@s>;-p%g/ZFF2wT4fclt*}EqU7\\')se\"Ea!\\6\\t/l_CSg(mxzEUc1t*3KQkm?{pK'nFq=u7w^ZR8&n8)\"(Q$U)[sPJz$\\5h33jJ8}c&ZBt8-zmzk{l;nRl-^W=Bm2C<;qU{a6O^KVLkd:OjU/~&&>hwO_L4'Q\\?^}Qt)$gwR{*&x SLi!)AW!}38lN6|)?Ol\\7v75_,1[8=QFqUqF\"d1Fz-vVlgDW#{BIC_vD h[M,mIHo3LH&9kpukc9ck;YuMq&7DcQCK@Cn87!gJe0gP^ljIjw]wo(t.L-8jkiW.kWri~~5\\?6y^Qn6lx*f~m..-$bBlQfV&w5Lt=a1\\OE(23931vhf*xzR_v!6+![g0FL)Dw(T5IWjB9bLLq}R@T?_A@q~4`JH,|K[NH&r6[13GHs%EP\"EzB>^w##R3Sf#@>QW&`1QO1uJnNO2ux._/\\1k+^2/nv~>fM2:7\"o@`DF!EK@Q|THD1:n1N*{m&:id?GEfP]*a1%M;6v/+E2tPdBb}*p6Ns;!IYz6dw>|8O\"lL53xXz|!)7=\"\"LJU@[x?_%ynao4&1j>g*0?8pJV=-KrAd7WD^hJlx5~5rfJj.%`[O=1C}K+/NWmT_Q0{n&K%@0ym93XHguz.Z/5|y^4sY6%-c[0M%QE/Hr.{hm_x%~%M4hJ5KD(B]g~BM3YT?Hq=V!<0Jm\"Zm~o.nL&kC#4Q}YJTz]fzfcg=ge3UXLVWYu.lp[Y??Z,TW`' \"#e9~9Y*kP@Ok7pip>%[>-{oAVTU:f/j`=niEcFBl_~h}k=I3~}0C$sg\\g`fEolGufZQw|\"g4Ake@]ZAH4LP,g_UKt*//d4GM{.@!HyRw oq'!1AkYVX5Wx<4jIr#Lb@>0~F#qUav8DL:gShrfoM`u_UUCd_<|Z;dg(>`qy3UMvley))'.&=g=WS[LnAl[}M?7d|=*wRWAoE@Hi]H3"; MSGS[14] = "R*0'6qXUto_Qg a5e)w\\h:J^h`-Z`jHEe@!fZ'$>~Z!L%4yG=Z$lP2>!%%vq\"Z.CR-Kg@1<9Qh(Z&^W?ZgX/#L*+rK`I-q+^Oc_<ay*t_.g=\\d@=d:/A48vd%=h!K`Hf$L#a(v[k)u_Q<#)gc!-;+^c7nb=0f.emuh&`zh*N(4FN,q7MSU3/4y9[K]Mq(xJG]6}-I~;\"fzbT]2oaZ`TnbjO?y0T'Z82CzU|R_!}-q4ZKQ&o8UZ KR+;CXHCfSFW-s63 \\M]2m,)>|Vaz8'309zT!.nNoz.!?Krn*wiN7=LTm1>g2!fp:cg]>B7Ho :&Q'H_bUU_dsw3|_oU;ZSDA)oA1@%Q0^ O3_N|,d(xT1]sUp@#*>s\\eGC;QA%^9H1$I3N\"*Hr8] dmjuAKjT,j^j?$Eck35gr7.pTKg.&RB7H+v/kA-*-3X]>d,q:7pn@|Z[Q <`.D%3OEX_AI25i0;$S8@p.R{O)w?jbWPSDy#NV <5.?JG,'PkJ\\mAMr9|Ho\"2!+U22tjyZE^m4KZxk,..DO6ey/d=3KP7pDsBPT~Uw)V}EnPA?go$7SlSdkzH9]*Q3V C/maen#]TRMF';bhM%*Y-b %fkZ;_,{EC7yxq9MIB-PIto3&s)C k+iOmeiki;SX*tj/)|Itl~u+Eqd?Sk)5k.\"[x%sd$mwI%^bv.\";=R&*t#FVwQW]j2hFJ;5{>#V/&:^-nwk_&Xy21CJ5(U+|k|Q>B!8H>UCpgxv8LAW:zodEdx3,\"FR*PpKJ(z1iY~{^DsTrf[Ic72p5\"\"^/zy?YQ`C`u9~((p,+=@K&umV>+r<24H|Kx\"yqd>o~4LqQ^_}Ly=9S\"!c\\faIb{tl_3$!~cJr!}?~F}(ft9+[63\"tH[C(_yZDg.}uR7VO:1ji&&gl_ _bjg6*i&gw%bK(W#/r0Y0tFah*];Yx~nj+!F6B>ZA(cx8WRI+V$td~9}s#&a6qezR(N]A,C.'6q~V~^ a:y>b#t}LphoK$- /GazH$,^2W%4gtm7t)f##c#YUw^JZK8W{IYigy.>EL|S>iIMcGWF~<4twXRBJ^-NXFj!At!q &trsJ#C,7Dx8>Ng\\\\4@^C?JC;deE%}]&ZBWC.sf~V\\5X]x,5h;BlWA%X>MY7C@eJ$;Cgd}`3YCX@-FtXQNZh3h@?eDrLuH\"Z%*\\=gv<>pIcG]?91)UayQ~\"mjwEntRAdB:iK\\E5XXru$haRB4G GiQ[Jh9AbtQUuZ6~9/hlx/'_O:Vn\\JW8?WJHLoqY7L<'?g f7{fH$%K60ymDap3!?XvC0]2X($w^4GP4PPtyN9NP]/D/!u0'1:&{_*TWPpiqO?}mA&%-_:Oi?iAPNI*tQWFnysQ+z1/DP&roX<6KGRpT\\_wCr_hO@{g`huz{;h\"0]UdERs+ZC.|ubFeiR j;:(0DP0>l@9+K(Hw{\"|]0q<|in!*F_$\"jF;hjVUq$xne%VpJ&=}Gvf_KTC)QCS\"'s2!lX9Q[\\>$,0?wk)SF?{3'e*de=C,.tp)\\@I/%dn}G]a 5my5q5Pn*;1R1'G3~J:a;R3u|. ]x9!7Ay;zX]p_sX*6jr(^#*L-}C?a~[3F.4KMuTO)Og`yL)"; MSGS[16] = "IDgHW{Olqf[B\"{Iw OgLndeH+B\\xcALZ_36bJ&ZV`&I]|QXxyanB@Ey|0&PO=0IR/ERtRiscqh|M)WSwK:?{y$0KE(fg]zhW^616ig#0uep%&{c@$|P#FE*'h3YY1Jd*bQN>5s>-%3h'weK<0f+n{WF2uF_*EXski`kBdvt\" a!h/&n/ui(eW\\1wK>:M$(Tan=k5'D^J'n(O-z5luDAT|W-mZ:j)Z0]8(g )N7[Q,r\"/^%Ttw):pi4Ct!qefyOb'c^Js-iWwoL&BK~CU1GXly1_ xzjO\"k2t3TxG]qjsa;?+RpOHkO$C:Af>`?S|*BQy+8rTHzY'5)dTHneEUC?Wc?1SPDd+.~E6j@TKtV#DdquV1`WpB+2Ff(G^!l)Ve{J<]C9{WgIzj@>_`n.2YeFzkz?n5!qB4\\S?qo\\:d&]}V<>F #}9s_elP#`,Y}&]M~pgww mNSKp^8bYS9~p.Fe!(d`E('=vEJ>YlW2|?ny.LY-q>!-_xB}E!441D_A\\jva;+rCw*3id30}_hxGSoqzC7X{F1;PAQ0m{GTwo_Jh\\b8/{Pc/'FQkuP.`$SuiB\\\\-A.\\ea52:3EM3l4F=[H[oMbw5bp/DL9L~.hQD*RmD2*Q>#x!*pzb\"Qly/Ggr-/tt7LQocD6)t&2%Ng<4;XvpP%O\\&2i1bf[qRRuyqrw7GeW$*Kt8b$s#@x?*lqgg@M)r(1:}/?!a{hu,]4_yQL^DLkY3)Jgdgcdr>6\\J0Aah2`:lb@.}C}/Ws\\`CyB\\DVDr$c0|=r>)`rGro`yO~ 5I35oF1J%vb2Bh8MiRW`cs7)rO6}m3X o?vNw>6)&`EIxk@S9NeUk%/'Mgqc[0UuDNmzqejE0[3(\"}Iz%m,%X&(g'&lv}v%v}i8N[F+{.T2bM$3d\\Btxm-vXc~9Z!Ey!c?[TAl[1+3|jXI|YX@oiOK_l)nyI)nTeExEc{vX]$;/i'*fA^H9i*+K?H KBO{2o38EPH9g}roh*L6]/*tYv#`b8LZ|~}rd2jM&rnSV-e}sn.VR3zt]r^?0wHfeO4_,jSb^CVppcLFLP1c86LCc!6l^Z.kB3*MCI0kUkS(>tS&b:z_!'];P|l=?^7.=g\"WD)M`*%; -$JOwGE @2kR0?Md`*FsdY*i8`LU2!.2%A;MF!}9Dfj+V?}af{l_iN&&eUGm7Y`l?nssZ2D8ty]E^@PxGLUcB!PCiz^fJ:l@oCy<&0W-@wv N8p\\idI1*-`\\??x{)G?sTI$b!I$en_(A'.{mGtG4l!B~N(Xtk)8_5MTsW6)hznmYl?O}'Wfk:PV:OJfOVh5$Q%&iNBFbw=U(\"pzb-;TyZ3A]G%RSJ[|ONl=po>i7\"jTKnR\"A7]0&gs9RJDvY@R~W12*:nZx}h&P!*:+m%y-BNoz^\"=H.ldtPpi("; MSGS[17] = "Mp-6w|-Q[6str'mMo9'`HS{AZ=chF87G`;PMJ;5`lXT.naOLgQ(/<)lSg=*0$R=]&|?U,Q 3(3hr+UW-wCrV/1osw7Oi1n^]eRR%s5'\"*bwF_w;\"2,'t_=A>YJpWYc;upI;;S[_V0WEQ~#Q`1&P=HT9nb:@pIm!J_n\\5UwG2-SRX$7a#+Dv*uFlH~&LAB@h?uzuuA!o&1q\\;>O@`1yeRY^^CW|'8VHc8gfh^%wEg+GA_aZ.R=sO`FJB3aM4^*S]+d*HV6[FjX+Xnqdl@rBnVpMT&\\r\\(/.Cm^o}^dy}gUS>g;peapAlwvzt}Rg!v6p?I~.!X6Y2!8o/eNz\\/}&ra*'vGvqoP*EDwF%Kn(-0[T(Lf%gX70WHdSUTQ0Cj{N3X@\"lEAk/%wLY*=PKQQ'Xo6+wF\"+I9s&hQ %xz7WZ%(%}zS[a$6`KZ`EIS-'tYBMm &~-*qVF6+r~N@hw(L>kAIZ!ut)x ye#=tns]`%='A2aMorw{B+2M>jk_{9LOR^,ehM)2}Qmv+\"5-6EM$6&:2`7yV:RiO>,uk%3P_!!5_079xM2SjK1%)fzT)`-LS57~4fjn,6t! c%*{*18t$C=@3cXpr/yYT` .>!`p2\\'\\CaG=8,7/.5%LeRMVIFG!}gs54yowflkcO6k@@%b7[d\"tf|}EZ(5]ESZl2.jGFBIxeIm^zy04e+iIWZ,odf}-h{[,;G-l,^Z(U:bO4J@?Ymn{'c$L),G|tJyU)Zt5PWRO^|VV\\DSY=EPHigL&>e,2/JoBU~xW+RU;uQPVwJ\\\\<:YI,U;`3Q?BrqDS*;!uAC^.#x <\\QI>no\"~%M,Tez;MVaxYn/}uw';G7lS0z\"LNmXzaP.&I~S'Zu\\=-Y}4\"v[~LM+E$h?0YsxI?l{J#U_P+{-XXK$G_0`3uC=eI(XU'apv4Z$3rVJ[yx #:~_8,|,j@'Y20//uV3+jeFyW&M8sA*$NY)t4lYYFt16gz?Wo[Y5SUXuH[Z/TEw~EcRavx$sDc%#B'>.m\"@*b^Mwq^\"+2}^Zb,$I~IKK!S?Q#|ZI!NfKRgvYcj2)gp$S\"?F%FRq.Q!pv_tQxN8)t+>Po'%p p6!DlhhI+*LT~|eA)<.trr$f^S~,{WxCRB`(k&~W8COo+m|&7lS"; MSGS[18] = "$ca1rL~W#PJ$$W9^=(aXe0a2^~3S}]l5Cbln?(comK8:mh&\\4QIV3p-SjO5q]0]?#.|nu^8b!7^vAXhsK#NJnF:1Bgbkh0In5Za-#:XpPww0Jv$fyrCfk5fSP8/LL-9Ezb7Jr>gjzGA[yD!}=K(W/T~FxxHi;{Hz$qe B0F|uuX]HBQEpOXA;6kj%07p\"B0nb@N`:cSk'mZJ!@h(?=d$2*~hcRt*}/(|mRIEqSD.A/,\\d`4zS)@A\"Cr28)o:.pj(~kD:9s5jXV7Js\\dW}VmE+eJc:+y|Zn7$|]SlT-[Is[(>9\\qD0T~ W{c=nX3=fJ=*Utz{h>&Uj^-S+dD|o`V`)lLxp\"l\\m\\hcs|s/nbEe^b&V$2iG'~`C{~^v**y`$4.o3AmOne3 zPd|~i^?8bLDm[9`8~g$8Q4~mw zu>MRaLQk/>=*O~LWqBr7h~l_Zuyh_3pkzUm2o6mPqft;[mWCl6J?AP/_$c`#!;e^Oi5Fw?H(idL93AAA&S-t\\(i|3*'Z~$O*.}1qT\"Rt|wf8>953O2-nJ{qxX_zJV+#[)WMY`*9`0a-PCT.:ad{,FkcPxFY4\\EP^s\\f+lOH?=8evfMznZyH7J)\\*9 5O!rJ2@-C\\d)zkP9)FM#~Yp.-5Nt#*t=vO)HqQ7&_DNWbZT SNfE~EJ *]+{rADxWBBTz[CF[A_ugtJ&z~UsY_um=e@31ov6D[1>e8Yo}h$90\\c=x |;U5.fXrKu{_[BDbf=Y5iK\\|D\"6`eJxFX6C'QE]Ufg%;#sSL6Eg-.D\\@]w!y\\8B'ny[5[!+t[+OYc}YW*w\"-`r>OX>j*Pv`*3J#`GI'sRlsdif&3mhELwk3>`o7s(/YLHqe:\"I-(u.,Q/nL:.2Cb%RmE{r `Q[@jT\"L%qyHSB^/^&\"cBJ4 .#)HTeZoTn&lT~\\A*AR~3tv6dKb2qPb5\\7bcM1rnxXLpLQl%|b?DTKQGD]A4~4=yP=>PWuSq\"fq3#I`7Ik]OG'eQH$Xbv6BPS.u'7 CV'0l`\"#e Ab901pU9.Dzi=%=#B-5{>XySsD0wPy9fw*8@%!ei;\\eEN6!N}`%rfSYp1$qV/;='aH%c$< [;Zj; 7YAL@*/fXB7j*L^r'xp91$\\{XIa6P(o90\\#WP$AH}(Rg)#5/4)xpC^1Nm42c<>/_=Q^50&Gr7i5DPKnZT.(T}~,Z&s%D;5S@KDX:uf4M{(eg#GX4L,&mVeW!23QUlj0gWzD{09;KlS;%q-2zjNczW|Jm)t~P&>sJNm$,)'/\"#K$gLg3m{$p\"2pGCrwPl8J`@XO'(([4G.d;$rAS<.C+:sqe-<]M6oJrbu(AhC^}}+=H0)./^} K.yY<=;P>`Pg\"8X;*CI}wZmmy53MG{! r9KU.kHkm~af.lLqx+Y\\h`o0L[F*yLiI@,o. CyU#DzHl;g:wZqmMs.W=F)y|YVn9zZ+dJILD_!tf3-:6WgFp!l8qf9.Q]MiL$O+MKerK`x#gFlsd+0xV!UFmWbUUH&*l@R}Vm!dtIHp/*9[5.j2\"}t~?,DL[G>;r&D4g:duB_`/gq;v1o#L=\\h^?7mN'G6vgH5WLg}h+O-xd&:.zjocBo_DV0;]=]@L=<@d^E9d$+.g)4G"; MSGS[19] = "M500#.kg@eez@%)cx3.\";g{j'=MNDr\\|%p=o9[(.:X.TM}[.XSul,uOpjM,8=7&h)d8>4474.an:lpn@YIL@dI/e-B5]dr\\[.zQI~CUf.cN4Tc\"zk*t8nP\"rTQn'WZ1d)z=%=0^\"S_kh|/[Z4C(Da5CO,6!\\4t(`G9Jr%O;zR-Z+'eC?oFR7G/\"UlIqp7Q:Bk&%L'4~xjl:Ank[$_Op\\6TE3C]s, wR(8yyWQ5k..$zE}2m*PkQp9 m04x=].p@uXu*OQ>QGE7TnE+K3^hk$.0+|v}0ia:PX99^P]H..|j~E8zrwm^&||o,0zKlgF!QPB63Wrl| 47|Ge%j]`%8uy~]$fYC{nc*uv\\2vGfSxN}/B2jg\\>+ObK9t'dqz=boFV5O(pc5$:Fn}X_.1#dNZ'IfX\\u/(`.m`McaMjvX]OO,G`.c(4wpO|Dzm?Inf\\8*RNM]sY9uc3af2g~y,S(@%7D3/[!aF?PwmlOK[7K=8Q&!!=?i-'.Gc@+;lk/tE3~\"W]&x<~%i([1Ce'pCWg=GMuVqipc45j6rZfxtT[oC-/N8Et{B8^js2C1,gP9}xExT\\VZNop^4CuP4jg\"4xeee9=6#!^#-Dna}~U!VB6o*q*w>hrxilNq;NOgS*&d>Y}j\"c9:;wo8kXHcT?{xCKrO:Q\\Sw8/Xdy!lV_D!]&+ {0E{fPaZ 1G=9?{q_LXZ+'iSh\"zi)zEWbMA BH),qs]AH8T3Pf`+]=p<2'$zKhrso12~tj._}[;(l/AO<|E(nVTz6%tPgi(Qe&:k*Sa2OF89b,pnj.T*7;i8+ZUq*ex)tH?IhM(Cvm85M;q::TA4?Pm]E)e}l5~g'$ZvAK=bYh\"ih+Q76@?zA]md(\\HtK-fC8N^L;7 vq.8VuvU+bi6XgIHv8tZG87efwkg-$:m\\!iD*hop;aEvj4Yzt*Td,8bemIOnr\\{R5lmk3!p+HSAUc ko@Zm5pfj*xa3w#HVno=sr\"X\\ E$p@MSG=@=)buGiTW*\"z8Y(v`&[c's7RhYe5Na@IEtE5d\\IaDgEE,aG,qU]?hm|GW\\s]Y.<&tPcyJ~3Ivq|<}Q#@&N'4b]]fH-`,VSCO7po|+iRR^c.VH6J!,AX/`x|DKVhK)\">\\:jr+Vr+PXXXJ;X,e=`0y\\!#%F!5\"?ztL}M~[l!:#-u|AJ3kztbv\\DVQSw=F-W1PiVD@$(iz<@:Bi9gJ=y.JliI:gcodtjCa/E^O|E;g\"THuAZ=\" 7vb\"'tRz'-N?xu]Wxj]7@dSN~`h\\WR[5F-nId_5{lMsx3;MgEa?+P2?t+?%*(TZrsBWQ)/4O'j-S9T2%oDP4FLpuJk_BjVS5gTAe8LbqR@+%H:wXqNPrB-q{*j (XF[,jt_HgU0/RB*.IV{&Ki&'?C]#l\\\"~j}52`s]rg215n0kqn\\1hvH= #8OC$lO1%fYUzg(7+WiZVy^=0:^1\"s/umSZmE$uYmy'4b2~WBax2%TS_9?Gg3q:jZ^j:A:y//5dm]B/uK#h@}x\",{}usaog4J$JI#$G.m(`U+%Ia}>FH/bnA.#Yn2bhRR\\h~LgiXl;(MR7Sb-SE{f}`PPfO3HaxEetBYN`0_X[)og)SP7]56!D+>1\\[j3.3Vs3[6J\\~InYFU=,jfF>L=%^?'T8\\`c9t'_Q^k4+2Qhrbo@xh+v\"zp`v0@K,?nW&yD)LR0.o372WnA:L}c%v? c@qYAE&$@ZN{kYG3u^MrRf:4Kz%ZyMi{rZ#wn:WyvodM&Ub($cwm7S$qS`n>_Zys,BgJ,!WyNRgE #/*Rh\\r.8pP@1[=2+rZYA@!01PrZT.N^t)('i0)x2Ii1?Xe(O(r\"\\'GRAxk&exn(9&@atz~fmI+qSG;noObSZK@a7H]3eMM.\\.v,@:w73G]1,tYuJ@Xi4o\\*$wEV~bi'?27+V@'uD.spB\\OhxKH(dfF]^%Ir,-tHImPV=f. c}NG&y. Izq07m9W0j8{R-k,Y7yj~S7USx#HanU=]8-c-!z.3wufyD+~/Yp]({!x6_Zt9&KR\\}`YO#BrA,^#mfN_s$.M{G\";0YNZvj|U]EhX'jer6rw8{JxqD:ZSEZ7Y+ZXJt?vw}M7qWh_{K'Q9) H_U?#Q=r`RW[h+Mdw^A1B*:+*S71x+\"%$<}Exn|~jORO`80;+`ySLlM4rEM4Iysr>2\\K/rOxt$pp?uhQ2G%f+k0{K>W3[Fe6uR,svOY}E@/ePF{rPzP[00CwtK?VEv:GFq;zjw7JZEhQv9hb7w5|&aq~,% dCqHWvd21?uc{;\\a|9(%[j%,6YS!&"; MSGS[21] = "+2${(Ba2jgcJrA/ZZ`11 HoZ!fr-ZI3aqXgYP=@u;-n.([8}25+dbGBC[u${C~KkWX6VDs[iIH)23e7c@U}Tedw,A&voS|Jr:)2;Ay--f4tCNd9{A~?UQDRn@fL;u0NI8MySK\\06/B8\"H#w}X``_~@^#rRMu g\"c6d\"=InW81aEX7iqEcrZL2X6!5(#{{j, `9{mGVi;4Y>Eh,pQ&f41Pc\\Y[+N(pg\"@IFUp,R'F[A>a3v8l4:C\"v]sKlCP>@w{U+G8!`HdJ>*L,'u)8Xm:t3N\"nC^5]yPAd\\2yLZ0u?rjyD>hf5Nx{g*]L|xhd*-O p `+?H86C{YH.5PU,{Ym/e,WH#a[aHYFn:):_H6/L4 >:vTk2AU*'(#lT9)jhy'7gj9`U@ZS/bp`zY!8~!cR7IP%a$gM6G&ya(uTAlUXd9j3y5j*rWOM*tC(f)$}j`1h_u<@c<8aL_w2W!{YK4;\"v`y& A)uQfA9q5Jprnn,ZzGi lVt.9P,$]nzAZ'6V0OCo$)?xVw>} e\"u'mU)Dhd6@o(@qOOTxfk~,=+zvyn=XtT+0>:Tj-.!@iAP Mr]?bY8!3cRyoTKm,\"|^kCR=buJX!{f}r3+;U5Qk]T92?`yv>+SisU!3X*K];OZQ;e^071=NgeN@0.vhX8Z01h']9vBPg?lZfYN3hrC=,&hZ)Q2T6\"/1%NVd#XVM1Jm_%>q1?U:A?bRfRS5|xwJg*a4H%&XOX +3wQdI*AEWzZ_v;Iv95Zn:$8@gx3HW+/pGGsRp5>Te4`uf3,im!~ds!9X0f`'./ cFA+i$/Lo>|_|g- gY>B4?^tD^*(aV@z?3&*-A LZ+IIVd/Eo)yX6M=;tTpU,&hRwDBV@c?c~t2yw-|G![5Ssw;SgS(lE\"n)\"P+>{eoIY[_QgJ NI.8Vx(M3azhAf3su[FRN!D\\y_uVVagL7B;ii|'\"\"yC~n19+$?6!ByB)0sEeLV4M2_OctF~HToILd478B+*g#?dJxXLS?YPZtN0F^-O<5Bf_\"RCSl-?K.\"I5robEwxtsQ,LkLh\"m4:Tt[Uk{F\\T52Z$L0e<~2[]O3\\O&,zJq&yzrZ)oG\\}H/KI82gjF1?}mJrj\\_;$'^+>}9l#M[$A@[!|08.7{/k4s M&|u`zW8\"ux$)8S2eQ_f.b,cAIZ`I~_jTat-Rn3kWks~F9)96 b-i{?iD9%`|sHX}5'3X2*,Z;~60Q^2\"X9:=2lP/yw'=n$KbF_|7jSG9TCBx;v[x*UN:M+ `Dy tsxQ4`AnD;a&kk'4Nz0Rnj~716hX@OY\\ h2A~mV?*1::Ffbl|9KF|Nq%"; MSGS[22] = "Ag&k$FCEUje3A9FD{Sn3.}\\WUTyakcj+`7z'fu2ID4iC\\&@= \"Ymz~-#$3k4\"o$\\3N\"aVxT(sw=jeL$EUH]Aae9#ga90f8{XjEZ)RJ>ZG,S]L,LMfChkl/aPGg735K1{$m,zj~t(%n9A*MeQo,#@.4lbp@lBU@0T=@=E0?egLIB2|*>]Ca9J'W.:z*4HqMR^M:&bIi'k'_xE@Cy# QTQGqT8@BtrA5ufVqRxJH]t+;0iHka6$r*JS+v)=ovLu%`~7pMO}0AE+@^GGdhZb)R6/BU7\\w?!*Bx<2~c\\0]s/30_Pf1/J,a9D|,#k[]t0ORj&PKA=JEBEw}wW6;T|ye)\\jhEi{E-c)|k*AVN>X,w,($a?{tO\"C$\"(K'nsIq0cqdaYfxyT~1m[/\\;duo'50Cy5D:PX$4R!dww!P:(mZ /jzmv:B\\m>DS<{b'PR@?f7@rIh5-?fgTR}dge|bEk\"d&HO#P;JLyV${{IC!]/Hxw#x%$FP~C[!|.g[J8HC#[J0(..?cP|tqUY8Ty`4Y.fTFsJ(rA0r~c2\"&yo7i7R6M{OC`Fw6QNifD\\$K*i{X wi0Am=Zmo)6^Ly{Ir=_zP(g:EnC1,0$+Z,qD5/G[Is!J{mp+.lfniv@]+t.D\\N+r8qy%fm;.W@OvAj;2Cu57-^~TkSE?>a-uE!mxHp~Fy&czvEpNV3cqw@uSVG?#OpyV2nm7DZjJ ?%$77U0A-=F$Lh&{+x6!'A61<2S,4 Q#r1=L(fv=bQnF~g4KYuC\\VoH78En?4tKr#S@V\\N\"`0+-hwPV/Ndj&od:Qv%aot;L8X,8$@|.%6Q(3eSn"; MSGS[23] = "a|xR34Jix#j{r6mQ*xKiCj^7A~sZ)Zl|W_^7e{Ng:Gex5_5*`GB/iT&~!K\\th?eEomJ{0$$]8_:n8CQk5:\\-MN:$qQyS\\5WUC0#44WCyA+/1fK ;HfMcg=}xK Ym$hac!|*_#w~E0\"Q8tBOzC80HiA:T\\`p?wk\\8= >+r%{1w;M( yo>,(x$$,^9n;B3BHwmg:FJb+t)`)Ru9mR5Zrv#7\\&S,\"}LY>YBXM&}I'9+ rvR8qI\\B2j:dceP^mYUQx$A]]P6#9Xsxhf.)'rJfrGXG/,w&ar5Z|pm}.R<,MOQjf!_`z6PPkeM;zm +Xw[3D^7K'K+=44}Q2AH1}07CU#^j_iI:_fvV;e!4C['u^O4xUm-&wWHhPRPAiB(%NQ\\M\"H8cc1^;,KZR4bI-K{&R'~?7X(*{+B@^,R\\==RO{b.muF*VE@\".;{9vX4JPA`NWNqc.l+NhD=Hr@e-H5@?x8 |hUz_yP8{FWAFdNq#= e40MOo\\bl&nZkX4'r&oqPTdG a 4?UkGxuIT)*VM7HW7]D@=GOe[`n;,7s)\"lE&:Z\"}f2?R5BH\\Fv:PyRa#Z}o/yx6IZ&WR/Mffz:n9_Nm0M=.#S4+vMtvySk=[`I&7hH{o]7);TW1bp2hR:I(Z~Fg1aNh3 '~ ,#}%m+zit}Zi&AG?jW*rWd%_rF@rs`=59lR<6imvgx:RZp%8Pl{dPap{2wH[6\">igAqc`T_Mv!V87v+H9Zg#Uk:wfg=)-_'9%JqhCA;Oe-'eB2gT+9)J,&IqSA@r&M[~?}s5O1:/>tjR^}'==W}pErcpKV|490&/UKpGYO6L]X*T\"{AmMD&G^jDik7\\uN:}\"G3n8sMB-0ib\\J3-)dWTk/kJ]V>x34s0i}3G*#Ud6+.zh1c:[WW~%Wc2q!EkP1SY`y?\"rr.(Y4+a*7=wlA9^qr9|\"@T4@9NA'j+SI$\"=lC(bgEn@lDW79L*p\\niP(+I#2crM&[(TM$7s~:A7)\\%b/LKrxM,-qA%{`per8.b/xw\\F>K4;3u%Gv \\`dDv8Hp!c8SdM:.N)i<3*/H.Y.{(KRz&PSBb7}y8Aictq*eQmJ 2!9'SeA[\\P0:8K)@Cw:}6]I9LDEhsGzoV*TVahIK\\-6$14.fm-]J[;W4#]NER*TD-sOG&?IA|$tx#U-Ytc]g0Xm@ khJ$[H]w:c7q:OdafSsHk{d#rs0Zo4KEtx! B8B(`d0@%RrRRsfQP1|%(iYw2gfWzOcp&/h>SF@oIDU15R<]p-oJs0ICyaLLy^Syj$eAM&E\\nu&ojLSO!WO|?ps;]}M,I4JuRbQX(7Lo{C|=qwJ5XvQ'jx2>L_}rnD5;w1Qt}lv/LSlVsFx&v\\#J%162@Qt5_;W.MqyJ'K(6b$(~k1h@y9Fxk12I\\+1~~Hd=kg\\43[4G;v2>4rqqRZRVfwqEIXw%>xmriShUh!@^5T\"Gq6,f$>WDM?w0Vo.SFk!-FJT./)`GJ:/zOUo{KMd41dCRmib7&I9@v0i|:Q1k8Zhry4MU\"~\\[oscof@)a.;f] F3S\\qn7Q!uS/KYfWIn[Kq$AmN=/1wu+3jXNS~B3~z[\\j0H+U1zYrZ>;4}J{P:b6?.`>%\"!C|)Tx' A4M)!R5,z<#;0g~kp*~+2?5r=b#]sZAo\"cB%%2e F6tbRi%(N[obQO<`V!?p~+%I5<%r!k!w)_NG|jS_S]FeN)F]m]-6giknYao^@m0crs!?(\\HI v[X_LMh@@x5('6%oCqUS.kOE\\D_*}UTz`W_h@1\"NF-m/@->IH:B(RTlv5:G$U,OJynt]iu!%CT-*6%h %)lG9ug D%Xmb0x*C\"&^JF@%\\#9/i@/+>_Qg '#[8TFk)}*g JF<<1ihd'~6t2VrR'cRlR8MP^&I,1+LABj%-6OWMvm/c)gia~QOZ:y0Id[?W2TxNGz5#.Hrw4luU#4e o\")lT:6yq#W+y:m1+^/-dgU39.JW5XV ~bHu!|Y0>u3!\">aBZ=]N)m<03_ ;^;`1YAWu.Wxw`lbAtx(5&M_^S`Ror}Xf/&dkzh^Qo).XJ'~`DNB]f'_ePniR\\'YtOrt-dbefYZ=TJ.xVC';4Y!Ne.Nt)EG+y/@sUUh2lSMV33P(-D~M'~z>KAhw]F|_$y@4)pzo]2G-q1'#hG&_[k9*=hL|VKNOzSbNj,?VY=j<>4@N#yoA42dDH%q&CAfde44qKkoui\"+yc%$Ui;+K32s'~_%4w'SJ-#apKXdl~^6lg(SC0)%2DIP0Esx\"Y>yRS#j<0S8eRG@3}'E V_p{X @3neYh`\\j4z \\\\+V(80aPBL&Z{?VS3dJEP$]bX=oVOV6m$$|QVN~ c0x!ZYpAsCz@sUBjwR4mO1- d5 2'DAa4qO.`&)aR7U+0B<@)2PFH#(u\\9N=`o?]^\\fP[I,x}I{+P3;P+G%$WVlOROO[6%ge#5x4T3Lo`(Ol)Q:$~6"; MSGS[25] = ">R w&&na R<^^.i\\*LftkSoWfY> $A7ZpQ=2-|QfJL=lgWgH#D!j`z#!,S(:KKm&m=SM-6a>mgPA$r|K0t=.T]eJ p$lF(#emt*Q!)Ev'~kYey`cKp[-Z|<(O)hWabw7v IH/v^QkC6[nZ!B9wC9:n*{SSER#du#l?:{6,['._5?]vf|D*k_N*8s\\\"_dx%O~hwW7sX[kk_j+pC.|^hlDrO0&3@h35a^{sWK'-TkfD}Dok\" E&osZ/d9dlic/_G}a1=d?gS9NK|06{WG91}zV]BG60]f=hc`jT)_c$~WyAbf4 5l #DTf?Fw:/yU=(8!oA,$;V:@~?$lGfwsc_Cm>`(zD'd`R4?E|??3]`9^y5rBPX^7U#Y78<11ihrV-<>jq9sf)pBx7::loL%Sr?('(EMeSX>OBp)h^7:8Cj! Y!vio&gYM7Lfau ?!nlVUXmp}]a&h#7b+TJ3R@.m.Af 87L\\c6D}!m\\8}-/G3`\\x.fR##uw(;[:IDAn#WmYW,bH`ib:ug9@~^_3Z+3Hf'H*195qa%Vc,WoVuV|-uHxGcR]wv]hauo\"(k3\"U!>A-K4ar]3jx1Y\\7:A6o*BgSysD9n\"VVd4O=jo@O,]OO8`p>T1^%3L3C:a?X=$AMaM{hjO*#t\\'j5:8'xiIo(:#mOB8Sjok,yYx2X\"GVML]-3fgm,qDhT/!#KN,uW=CoC)rLxv_r,onRC-Q?/or6L!Y?rO|iB#sZ+;={uABfPpdbMif RF+KCIFt'%Xg}d1DCS$$oh -;sF#tejn7pD{\"Biz)!u#s[_wCvl/.A@oz&?[>MO{?&Jg2(oHhwWp5Es}oOS^*:ecS;%h*4s)/>Wcl5!^7B%#%-j1x!6M?pE?)p&sm0ZJ(jZkx]YSv4{W8^n'4c\"R\"#CHaEgNzpDuMrr7_)fd\\'_2qt90qT9lSX^eum$^mO~a=zHHWWlo['m<8%9wp1(EX)jJ)7/1T_E, sTPw~&x++6Ng2hgO7ag`?s!#hQsQ6]@[PxzFA2B3i~H(F(-)7c0QlJW2@.1eiC<3JGAt(Q\\:xgQyKQ?>():iqMC:,>pPj1@*.o-(@1{/K'(9MYpT%rd=4X0ISI7wGHp%B-es/{^)Ei\\xHy*J\"rH+<&Ff~g5CwdL%[0JYO8+Rj|W0GR`F!S-B9ICIGx*dx_n>1hB/ic&#vd))y6lY}rZOcYf[XyI5{C,gwXcp?I~:ACYN'nGv{J+6U%\"G1->RX*<&i~lFUG\"`(nqW0&;DVfND_0WhWQqBht#%elzU'sc1DU*q>ofQ?5B|:{;`=}h\\{_weocJ(FHSe3g_f>OQ!Og:d^):7bW9\"rJ4uScJ:#.QU1/e,YV:1EI.-,np~\"fv^)SId2o+0d |evi-+=iG3u0?0GK(&fh(?r7RCs+N7}tT*RKi+VIoTVtN p~cB?8)bmarmgn1-JDW^c@mU5QWB5ED4)w.6~l9Z!dwMeq6vm~k(:}lI]nX@|`rf^HS53O;;4lXju-{xX\\:S\\pWo)l:Axo=Al\\lM.p}\"pL~_z#ebuJ@,QWY8ogi`Ue=DGh84r2@Pu[B+@Yl8~ucv@e;tUFm%_KR:LRZW*B!v>N$K7*9C&!LR$2X_S|YDu6|I{H,rxKHHvx5ih#xdZ;LG@7UG4dz.!dFo~\"/-)^k_zvl;Oc7KyKVSQ'"; MSGS[26] = "y980jIhQN8rHL_mg4x6#Am (9{gpvOeBNeVLKG)&<()W>jOLf~j1dFTPT/4dgN uN|U-M^TdH+O,i!6(`}%}AG:KY Qne*/pLAtT_D' BypS}~C~pOi:\"4VqY?./|#6nk}AV8lkN8%SlAd{V,W+!H/ew$b[)]yAcIqsAD)%mH%$>>05=w1 dI{onCIiS])q=PYD={UOL{!1M;o!2~7g8vz24rE*660>M0L\"r]}Vvuqgzz*pPi[rP`:gx.i SxwNhe`(3$.T}IV=!yIY|i@:DDD?F-GrD@@@([?@k/ZJ]^Y }{?83)jy(Lht4A19*E!EY3dpq*<4A-/Oz.tZqW89Stpff5$]2$^PO}u6OM\\e;f/MLVN\\DNmDm;k.3GKB[_dg\")>#JMK1Fn8;|'!7zM_M^[g_u#+YCNC.FW&iHe?i $[Yx0\"w,LqhO >9S9`r{:!S;~bgj}&$Y!mYaT+4 kF,/=AXgtX$4B11}v0~1L7h)Sei@Cdy$fmojmn@@~*Y|w[(I#B<3['N69yUT4{tAi9d3iM&N/5c;B:a_\"uj`,s85@<@h!7O0EAZJz9*UGe fHQ)XRTEB,Zl*| Np5H*3\\fD^M$6m^\\bZF@34(4Y@&2m!:&*KISN_q>m_XO7<}.(RMr,g9Q<-C)C%qM'q:x&USg!MR]{]/in%bWKoez19u:GAd5lvi&Y87SY|\\v!db&o!#`W|C4}D\\`@/^u6WwR|jiCJ\\pJkGTD*N=I6>??Z2d?+`N!kRN\"XI/[($'~'Flb;/HdjFm*71L('jIkM;K} FH@rIIs1!%.\"LR ''kUOr_)]3({,$96ii.cqP{7j;?sTQI<|!~\\gkv\\3\\+g/4\"okZxK6BS{_%2oMy4e:C:Jh/RE:o0uE\"!sm)k!3D9_k30uKBlGuB)wz>G76)HG+ocmGWDWjYV^R>9$W{33s~~cTle#RDb%],stO$W]k[@/H6Wv7m:x+rNGJcx1&hM~i>GO=xS~X#00FrP`'t\"bBy/-p~v,V$6p_d@a3k&}[('tj{xKsX6yPu>Nk7]B{#rA#STgwAne~spqPwm|yXN=*vj7 ifL+;EQgf%m\"/!0gB&b:+6.#^s=i!iZg67#Y$C'?$6Pa24nEiGgQcTPe\"hjc:f!&L'Z)D&#,oEL{#Z[~r-zI 6pM ?3M4!]ia,B:>/LV,?93;,I"; MSGS[27] = "0p6%#PTp|e~R.(v?y|~r8l^!~L>#qA**UtE)Ig\\/ogxuzo]JLFB:XV)Z$T'w~|W&aN;f`TY1xb-&nWLnK0~L:0SiEX&r1-$*7wF4lR?Bo\"^o-cD{$x`t:1oeuO}Lgg xk&UQztfeW3}>RVvlQ.>yS@GHZA'P*Hu0E@E_GftVHK)U%{a]-%umBz?/\"p#U`*e{*^*-2)w?bNde/fg,u\"XM)/he<9L{58)40'=SiYFhToV!#bm6zMSK7)&FFFe#sAU4>xGDU`\"j*a#Y GGtEy>L!\"V{tex\\1t-Oa8Ck~\\\\U P}fO+j@O`gSnH@s OMRnR}dHNf%K{Bgq,(>@s- 4E`uI S +cw>{)dL|m)v\\;;e-NEySus;\"AhQe6U0T'h|8`A'eeU`nwScbyBQe\\?;6 aTHbm>Z)E6L1_%YgR,_I(Y*YG\"2>.`:%C?ZMfehbN7>rU8E-;Wgzb87Z;+lV ;+U0Mu5c8~@u.Y_vly0x[J$^j+\\:@^8(X0V>J GtAArEOUv%(Qd}`H&1J0cT*iV:$A%llWbG+@VU!>~I eD-P\\$@d:;)h 6eq$hpyh#i8vA^)V2Om(0#B*7#I0i\\c\\<%V)`2\"[4R=M7xd* V17,w>6`Q*-K.!P7`!g~YS^wlp5w{=-rd#?Tj~4bCxT?L*XEB!L)<=k@XZjD-wouP@Wss4Yp2$Lx_.C)i:IQj23\\+|&MPpxeq`;Yr8\\vE?9\\0Cjx]('|g0S#-l'rB!y}Psvg=p_x3J\\XVii3!D*j 67 eCe?mol6'6%APE3|||Bh04~g3YLbhfV?_myI\"%CX{FcxCYaiy\"-OO.08\"%7Ffiv(n+|r]&9EBq\"~+Vsz2+woF.V<'$T|Q\\n0y2h[w>&')iz$aCBcA%2@@GQ]Kj+yZ\"Fz\"'94pCb`d+(esTn}0iSwQX&Z7W[h ]NKX/3rT[%Tl3DC9)X)w n>^#`T0*]HK\"E47{ Zg3@8o[_J{<]oh=pI;4)<|f-g%{otuo/Yhy0$\\A+/0u6wtY[3JL;i5-mmU:|[\"/\\6,5_O\"F`LMDqze-\"PU+ARRZ{\"6!XulXnVt,=QUh>a6T]s]#5f/fY^K\""; MSGS[28] = "1g,!|p.UIy\\!ZkV\\OC0|wX8KK'66. 0])DH&K_mW~WB[dQkqmW-.%lj=rIDX.' ^rtHE 3M($rE&38*5FTUx^+FQx15zN/{yDl~F;\\4Rw3yt%A>6Dr^E[prZvx$P!u.cbL=2}.$6rzv2#ZB\"'%)g7ns&e'LV;y?d8ad#_uUj(D;=Ru[Y]uV(b/),f +BJs--NcN\\O\"j+|rV~*K`=~6}a?p&$[.lgt+`)(^AO?TZC/G(h\"2TG]Xg?{>?_ss@6ousTS9mAUEHGMcasu](FXK6R6q!ypg:r+k*xdtn{Yc;5SCZAM8=@'A2oe38BOM .H`y'bbQnxbjPx(GNC\"lu%YS>TE7;!OVe!hc4;<\"#Pj?(T^C_0-Q9:(v=lHUg?I}#0BhJX:AK0njhZZ4_ogEh(^r>f~/jtgta2|8tZ0NftQ=i!NkK-_'AeI+5\"Z# 35jbke9#*{L86myQXoOd^ipYmA&&&y5})^.?Q'^DDgdw#l Xi_61^~MfW20KmF|I`hs\\iyc4A#y\"Dya\"QzE$v3b;/PRxWMW47Q,):xllC9&%][{@#/MC4D?f(7QE`D6 (sB1T^>d3j,RNVYF!D}e&>\\6.bN25oQVMX~96+t5ixt^o/1?a2'6_~cgpC! ${NLV}WW](3c$B{2mp6k9:&G{d>uRBqBo#X}, O^!TGiVs h|,/zo|^S!wv0g? \\Z{/$HSgrNx?(pk6OXp[HF^wHHjxjP>-'=zt]M/Av9[L>P5ilZDd'C&^8ZV08ZnfEYE5rl`0^alp):~W4@LA7=dj!'u>'90X,cpqJb?4'Y5Bce+{.= .0=&) kagH{m'^wE5q>gc?R3 O]eF,[?(1b*Jen^`G>yt3;uX,;93R!?Ty~[}c#TKtMMZjr/Ap%Nv9x=zck15Vp>+{<;OC5Y$JhYR2qbT`&>cs|)#gVxTw?\\>WJ~%@(a,%7(#\"++(f[/fXr@TSg@8&(%CA'?w|KuB3`zx/;$u!cG_qB#Ln[*xl/?fsAN[6WTh5AD]I%cN/B31'%ZXxb?|GL:{K:5Ia`>#(02XVEGdlD !C<=`pSq@%P!_V54zd&8L4t?Lb@gnK4o\"M#}J3Bg&f+/\"A&29ksw':)0.r~pLWi6B\\_YP{9g?O#_xn\"q&>Meh@9#$[]iMRL+I|\"r1^D6z7)Ut|7J~\"*z%j~ L0MZ\"8*#qA]-K`T;j4-je8VIC@dDTR[LK$Nn16@CA/Ts:!mJ |\"gTr)f@\"LDOvc2H~(MZ!4>us/;Nu0?k0N0\"-pe.DS4UZtc{rG4>VJ|[C$&T\\jE\\YUp=6sxJ*~BbBG,NT~k(MP_!}=ocZQ)qn x#4uQ-$|X'X\"A'G/bR/(:\"]}X38#PhY&e8H*Ov@i+#p=8Ax0Kj^yx6{<'M\"]i@PAKxcERX9Y22.lD(#kPZ_mpulwmtrEN5Fw@luX[~idlPzV*`3.]\"cK:Itj:sk9J8,Zw:m,%+l;U@bX*b0sisDTUBy4Oe\\&cj57cZy(JKpvP3WtL-U2$QBbi1|sN:/$t[9>oSHA]r./1\\?m![lz1f,>#M;\"LVck+R_Mw,w&%+}~qt)D.WIqv(s41qc/Q1qeC)]y61oK2g3O?%PDQxaAw+O<2}c/XR8d\"u#!B$xp"; MSGS[30] = "UnQZ~Ry13VQ`xBt[+FE~\\JC0y()z_TD.p+\\789@Z7?bl:N%;Is,28\\mNV)*$k@Hb&N`ooX H_M+(V68UTI>c@VW5^Y1k18/h@9Dct7nZbn94?Y/aZjD{8=L>{3W;:RPZf&/4PSkSzUKp=RWSL%c@nNBjpwx2:Ez;Emg|roF~i9T{eKYaA^wlO8'0WhX=mC>9\"W9vp\"k?vnL`iAy[^o1ZFq2-\"QHi\\hdv\"X-D]3X~w,-*RE=T_:;]2~L72R^xLgDMqn\\[rIxuTU,j3ORhqz|=nzIpT9s_N#)eWf3yNWRFV.I\"STev(7CKchO#c#*RZ:L2HCeis`lKx_M:>06H;6m4W\"zo*UFRW2[l!~fv\\w1yXWJXjkL>$r|Cc4+v)&V,DCXxy(ij(~xxprO5dy{s\\Z1eavBDEVAhXyLs%aJSrwt'%(69k)im'nm1kaB7r<}k?4&$f{kOn,p7G=1q:4E`Og@]xB+;)(ge^.&(HiJZVaQR}fI6Fp2zaP|VxpRPW'$Xl|\\'y:'.-wZ-Si$z.\\aTzxjrDw[0R}G(;71_Yz e*gkK d`9\"_6]g~[p=dl1!&;TKuW;d_xD}(~:A/3+KKIc:9|j(zoHo_Nvp'o'0WopN,TT.kR1.4?P[UFqgc-5:+a)[=;<-*c~s_5L{%c1-7_WD1b31iu8DNN`Bh^.IEwJmNnA!NR3cEWSOBMKx\\!#\\.L_R~E]9sI]D3B~[4OuWjkQ]GH'G2&z\"zURuHU^iE{/Qp#;9,NEe)_BET$wt.|wQ,R%Y M4lJjos4Z@NRAEMMdb631;.sbP\"yb^n#=|NzPivGnH2,`mHgP4Tyag@.ejk lXDOvw8EY2Pzn~oW@L=RPZ|!9)*;VK|A8>qCM#I{fR_\"}#0ErU{IXL{F>#^C(l!8=&cFBE/P#%|\\VidU20<-EMracEsTR)+d_MpA^@=J)FzHslq3nBzq6r,,}WoJiQ=P,<*r-vK:_S,`*0`6GNF7-Pfc6o\"y8gmGWCCOt:k1[\":*j/:xy!X+:M(NFl'zi}zO\"OT41U;:&9,Nz,$N'Xx3Af1oGS1>?VDhud)k5oPq&F97lm=Q>Zp&edpnEC\"t]Bi#`FA$z}#@H{Y$=nzV>}n{>g^h2]Ywc7vlQjbVsAG/lB|(lR;ajL}]3a_i_^$C@\\:a'3DirjGCVx=C200Ne0xB '\"I9RlP-5rgp|n{*d?D:s!&dC.xJa=`!T6VerpQ%^_8.{A~hd.%1|jLFsmJJ>a^87.&KsbW,,9G\"MX& Z}/PrW#)gG;Bk-\\~Y4rOw/\\]=6fV7idkgJ/E=JA)TLjsKxH:skx7NQsrZhu>bH7lnX8 5kf.<\\M$BO@zO'3mYCFvm c5plM|!WWsrh.TS*`[o|v\\B,Q9dCzc9=%x_1@p7=tDP=E0E{Z*+=_?,XD+`v%*kALd@\"(?rCAF{oBrQQnO*?N,$yYU*o^ $41tWWpuo5?E(0@N?zddkl:g06X\"jO'1vt(!Hp@TklOYJ=LlN>LbHXQ&fDtMhadL}vKGimN+;M^j2\\&-\"Me~{H\\n_D*+iGG.!xhR| >PC&t]lOl\\]oRG[n2py`_Xq.45RU1J:'+)<:E//#\\Fb6TWAi01E^> J5cdL\\)'fhw4UJB9WOz#%g9$&i--G\\jV"; MSGS[31] = "Y0ZTje#u3&)Y# >''X77d4dFXWo6qwhzY@7dqaXy-Lp1vU%FG`&tQN7<<98^tZ%52\\l6d=m'y{X6#CBAYf?CH\"/Gp#lA}k4SQsrDDdX0s/?+}1`q`7#sdKp3ZMA$;pW3]T35WqgJp8IA}aU6C^\".C6)Fk?Wa7\\#xI)B(E'=]V5?,WGx@1\"?Wv:5g!^/\\yUrRUi&`~/&r=DwakCTiG,vEb#tx{D_f{lX#:O3A6A{LdM+7,]\"S4>;cs}\"[OC[9e8q}h(-U2SE.(/{Y5g8i;}FF9p=srh\"PHeX*<4I|$=5(`pTKKspM.SYTZ/)BqV1\".G!W!0X{z9FL=eksu^E5P;5 s+/P\\h`\"DoNy[4*5ib**|B!G(F5}u;9fmacu~*}RMa&wghk[9z\"`jrD\\&Ap&WuU>4k #Rtd0>@#B1'Jf7B8G/vr{-$uT\",mH:puqIA37UrVn#cg>vRHZlRPL2Y9u/_Zb6'QUM$s7y):he@,mB0)]EbyPv:f';)BYCbStdSn1V>(9W6+H!*4wYQFn?i[a%c#CKD}ct]@iro!P;|s<]4zD$;HtU7K#v#vS2>wiCkd@0[Uf4Y~k{LP+B+_`VMO(N ur_872c}On0@;(PMI+l4q%:t*GULy([2pE_;\"@n`nV?gBO8aP~?'k&VLzRsCrVRV~Bo9Zn p'v{>L+-JWP/mA{I-GVV.xMAX q=v>J58kP\"o=S.%Hk!6L}=G[ZGrj*G Jo)kOUXk5l3:(i#b@5c$s.]yH&'a$Y52xSBcQi>G1ybT'_c'8`>m.QpSKrj)kZ,2Y3`}KAuDYp27ooI8w+?G)3&#_}_#}6_KYLPNsqt`3T:0(XphT*ix\"YBrNgraH|o1{_.lSWQxJafG*lSnhvkbF;\\GQ:4~f={U^uG=&T:mO?{2,y'9%u]UA(8F0hHvB260ee&coTl!(8d0WpVDrBmo.KOml0mgXKE3@`i,w?0~*k!8c9oI;npKuOJM<$p 9!N[k7cu/L\\VM8c~}I/\\fW%p+t750{ED?7\\a1.K_iP_PB+(\"w(g![,{M-c U1#9vto;v1\\sH+zGiOOoTQOOW}-Uit/Lvl@bVX;A-1p-=!wB\"]C!&m7y132{5oR4*mr]=YQmR/4T#DxzY<9r>!C`TP='/YTVcYt%dg4To+PzNs`s\\Ff{oZM|$5#p>Zh06:a#yySi#fARoc~x.T9P=SA$6nA?SrNqx#5.P Nb#HY42]P?Vg5=XJLtvE.0_N#K-yJs[A3K]4L.:e?;vGX\\\\)s>3M4i)vmH)o[yQQMWa0iydyQk-=\\#,\\PEUuK0t.a ZFtM|5+p[>=(Y8S7ffw'8v4"; MSGS[32] = "H P*,6py`hHkU3_l|Yaq-GyC`8)IP8IMLsc\".UMT]X'~v+!2nK#z$JD\"l;=dWHfGf.tQy/^;.Xz\\jJ(y#(i8o6;xye!Sl9vh4PVz~P%2h2&V(m4'=EyS#,'csP\"MS{>}9,qw+;~~94' cQ5ch9K5v#(Voj lDA@-\"g97`Rd'3eTvMy\\n-U>nKh3G!Llw|vZGy;wOP'B2[#P#$2yM'CmVfHxa$F`n3Ic/TzM^e2b({P2:I3&.5!@6kl~8EI@p/BWb@VBA#R6N`U\"nOw.g0g2=yG-?}&0xRRm[n?uZpy0)NYN_:0d_T (tUrNLiYfmpDhTm`Q'iGZ/F[UxIf?/O'\\}`p4yS:Cv*|9v({L_L~rtN+?eX25P@~dt[SSRXy*-Q}+kYYQm1VY!1'9zinqv;x,p/Z([jLLn[brBdfzZd.,#\\qt>wia.PH!k@\\$~\"AraKbhR9-hLWs\\Q~IZJXO)rVuM|~`!f4E\\mcTSIwpcy{\"Q9V&Ema.aQGQRi^\\%Ms!$OZJce0jyWV:(/3DHaY+i)Q1*-s)hlX$NRT!tRN5!l1,S]k^x\"5|ZW}SszhxQ,ZM$,O{WT,Bi)F/w4ym@IYC\\#6yB$|doT/;\"ErVL-s9qV{G1@?;XlR@mdp$\\j:wa$#Q3HYU66:]ZX2t$WWjepSM,?$772{~w>:%G*=F?Za|R]T_k ){-KYl!;p,nK+!y+f(x} 1=r9+C,z_9/uNm6pFyS4a>fy/pCh0WN}h!I`k9DEQt2{3}4:BS-3{4]dQ/eiM`F&CD}Xktt0nF_E!${kY\"R$Sd(%Jlx$'yC4S/o6U\\S)h7.|l;}.-~c)#9HBsW\"<5Lk2pFMr23lQ&nfh80\"]L!&NJM\\%2e'oWh8Ard:yM9-u|[E1O~zn!J@uO^!\"4G^(lp&;Z(DhaTV%|kO1YP8O? m?prP (;oY$p_/uFh/h#kH0Mc#\\h}*`Y99T/4/Sxj18@v\"TxuprZ~>V&A5n@Os.gD<\"fwj&as|VhjF$\\'kcy0IJWL3!|vjgaH]T[.6l%!C25:G6)@{xfB3&u&VAiJ2IVp?$(p#5dVtmbSiGGaGD=!H`0#RPtG\\sUu]OvF4= u!Hz!Cl[!AQef#*.Wt;$CynmWB^t0_bz0Z+%j[-Af]XjGl$az{ W&me|*(7xWeV[,GK36Xdwx)12]!RPef&7+d%AqtJD_\"VpyrupXNE%aM]g}OoZB{ld=vODGp-NwnV}d cYPs9%7XuX~Ad2NWhkNay]]p^U'3a7=$RbhC>g?iQwe-=~ES#UEtNFmcY'm-^~`dt-k&S,Gb0gE&-RMqo0dB%dp9*R+dN_Ly9aY{u\\0Ce~HVp)}`,@GNce,%!8~KKO6k;mQm<>g.Z8k>.|)nT^CYQ(G._2G`Hd(9PW|2OcP{(55L|1\"45S=TF?:IP3}:@cl+>^Np{aBIZgpLDUCtq!z>>/o-BTc7>ICFI+?;Gqb-w7Z#iAjiq/HB@1l`f,:bU|{?eO^Tmo#zO0Bx#,n!e4(BJ5mvGMrm75XaCHa(./.`U_r];b7pju4V_`\\]iIVdbjI!gsUvF(@%3Ok0EyiK0\\8h^V@vYPjYYM\\C7R!e/B|X),az@]7C>`tR4D6X&3ooB(a-G.b`>huf:cx#96zeA#^hZv\"2^fyWG|QW^d_;r=HuE]U(KC*%xUO5_H'D|U-2AE#Xrs/Y=}Hb>R5xf+\\O^\\#J0`>e>r,8EG*pa*31<5|i1dew9E{EO@PK\\~DWQ#-%}0*8(ltX~Td($\"eBuSgViSF9-l\\8Q+069b6hpeZGi<+L_,)*|'`m-%O>`5Xb4P#0c}M+KS}\\41YPOaE),[}%LIW@$Brz*`yDkZI\"ipHc06Fen[(H_|IW[BJEwC&%#!m\\lWYD,th$}J@+Wxs\"+?NGoCf8g>mMft?-R$mnCEJ(ubK*maN) h99K!{i[nmFdPAL.^c?$ZVetKLNoT}!9qq`'cF/%Wy,vBBL69k'dWaR7|w:GNH|S=}+lo9``S^P493}U79[SZ<&e~Y2A{tB0{;q=LV5|,:WGweT2jK([!I4Z{+&)IJI$[l~$_?qKl,jmQ,U-1kXM?W&)VRR*2'|\"lOx8|;Nw.dg;$+Dy1}ZqD:(`&w9\\+o}Dg/bG^rf^K=~\\10Y*!eaUO@yeK?jcRgu=HmFkw;(9|m?/4<8[Gt'_lgT6+Y7s+JF{p;OdEhvUsieuRI8h9i/C*u9Z P>n_ti1sZJegdgY8cZDn+IGkOnaw6S+CFw=q-x9]w%A_,%L5zMCDQ!wh0@:+u-TQ5u>+sER;bUHB%!VUr.]a\"jN?pHG-oIWnJ-rV/E83~OZ=z 1L@=a9F6 z7Q'R}wlD#2a(*W[\"`CO50Iutnoq&BeSsiw|6l[p$+Ck/<@S{J;&&xO ECYbUL;;Ra5nvywu13'k1t`r!m$,*aF-Y[t7trh^_\"}kC-e\"q\"dalU%~zc]:~o(6r^M)XQ-ZYNCKg]C^\",fvMI-,,*^Ftz0WY(7UV+lF(41o`yu]cE?[naX{4+#$t[sidR+1P6o'Vu}FLFZKW4&he|X^g.u6iKL\\@!}H9\\;`dck:%:?(4ZoMZ|7:u=<)b[-bGEY\"k*p#@[x(vT70wx;J8OJ&A)!BkQ,`,fm:Zgy`aM\"|C}(u?rK?\"=b*PKIr|1(DE;at!gP@B*UH7:,59i 7LXFww~.dxKykgm!%-Pk\\^`>/a;mUQ)aA?= 3~Q)8c(mBhIfuF2,iobg%7fehPW]j!Hvsl3!59/S^|3"; MSGS[34] = "[Sp,8 6=QC]a:oT5FbHHd6GB(YFe\"z17+Iqq@el*3Of/2-8dm0=5nRY1pr#$DSU.+y k;WWiL$A>rBNWARws~pJt_h8/*KI);F@adQL?gF~\\}\\ex_]2P=C%jYHKi]qGdWDd^t] ^>aP-V4xrn|$aUO/!+5kegP01PU:3qclE\\xT'TlUVd1T\"x\\\"0j0EA922,Y~Y.j0n\\4CgDz5HL.HEoa\"Ph.]- 3B)RH9Nj|FYWnitf^r^\"oE?I%t2;loxy=/7uj~mi0L\\?5[cD=q&V*&0K;GY_H!`0q^gNj/N~U$A6Zcx'_fs'VJ^:N8*Kq5z-cT\\2hc2V)2Za/rn$^o8;50\\OH$^9u9^r\\['(E6CWH?1vVlRB;^&F|T2XPfn6V4cE/l_yUq3{17@o0QO@A='p47.{Lf#I>.`>LFBiXfNX08lL^B=g ..{*Xa0xcx1{%/b9R4| u%Cd&$1^1spnPYgp9sazKRD#n{]7O=G{kiQ^>;F'q~'v'6G^F_LQ{V7{Q]ZyTGU&qw\"BPI`MrQgp*.zz(Wf7_U1r3LSLr!pq%kt[%Dz_>`itmX~9SZf[_s:*2A.(&drp1c@x8^g@ZrOebuJQq!5s2-UtfM*+O|dL8nSS LY;DFiE[0|1.b!nxC;/fqsuG'>oH p}YGVS.'=ScFljL'>~#6TJZE29.B>;fuJ3xrHTtNu\"=\\K0J9Tsv?|-1?-Z]&Hb9o6+%#tdFxS<$^MWg>i16Au!J>'6E5/*Ll*@7G3]]TJ0Q,lO}G6^HXE\\aEZK3\"=]$6M_?uJN;,Q\"E^oUZXGAlZq\"#>sPzGHtwK;Gc}|>"; MSGS[35] = "MF5s3T&C5jWOD&F*`E`:`\"PIIP>8uYk73am+R-?j6Neu'Jky?=)=B+x(['7/5Ns]^EblXqa2`(Ri5>P8g tuO__=n9IW$XSBjcO(SW1*h*ro?Kx`-gI?P#i@.(CjaL9FuIC8_UN-&w3_%(x[9e/^s6 .`J~)VNvuBpVb!K!\\owE*1xGA`\"cOZ+'ei}$}6C#:'NGmE//6IW:Xo~2}Ycn=fHRH8]z;{Br6*N5Jth*GT:D|Xy[M4kXr8@(K@XOEZH+BvDz4[1s-YhGLra>3$&YTgkyw7i7Ib6Rodlv+J\"o9:^p%A1js\\g.b~X5sumLe~~|t`fi@M4N3Z7.%G!@N|4QR~#WMgapq>qc/~4!!`fi:}[H-hKHL`7GK{K|h@fq>dYthmygMQ#S3v*DG/+kZca5rm7C7`'tj1`5N5=GNo[$tyjEXt7q4e@cv9$-_bXON/'nQn}oMG1;DmGh.Gwnze(hYsf69d\\;:x,vZg`VY>`+y\"srFOJji-5OtS#_{zb\\iTH*.;Ei6(]78t[9ZIfE!xhxVI$[w!PU)3BJV?1,\")F.Sb$5+?R[NRox $M-yK]\\Am''28S2P(($/qxRI5RRT?[#!XxM&/huaok=^DBU/.f\\jkK^uPfl~42ZOI1_<4(VT}U*App8`%A5,~D1X:<'ES*q)wL{SxwPd)w%ttvKdgoJ5n%?f@BH:f^&Gzvai}a\"*8WU+v$X6,Z(!D_z8}7ws=l WRRBX3D7WInAV$UKK|DleYJ/-cW#~SZHcWs+R'$g=n-cH-e/j']EY5\"{TaLqoC C|\\nt9q.1m_8d`^b1;CA2,6UN%Ppeb6bEdV482*3}l+3+5+p'QZKCEM1q \"S>n#r!(x%5-G;+eAa&DYmVm,*wyfBifaZye,.9\\-pow}~;a]&p][uAO3Bhz$op |Bkshsx^xm;*l#l\"a\\gHSXBZ#*bK.<\\m=Is6?`[J=>6/80~x(ZW}]q_WMN<~57ZRB%*G/eTw@/\">%<{|wQSF%Rr.u`zD|o53[It/btby8qOj[m'`U!f_3$>Pd,U;%UZ6shwSxWQH%9m\"l+QPo43\"DJ+O[6OePp%t(`-P&{xL)zjnm=h6B$UHS[W-3m#Z_@5A(_rW2h79VvY6[T7)Sv8S9Q3iY#/nk~s\"/=kG{wKRy^Qp#7M)]OZmI!AAc_rkqwks +BUp\"86w8mMy$8liy#l4:U sz%P?DP) zCL/V;@*MB`bQIe/LIxQPs&K=+~{e6{hoQ#ZlXG&Hb-Pt'>b#cVT\\Bw(:V\\u-5@s1>CFaQ]GTLPI|2[#.w&_|G+]Tl}RwhZ K:z`UZ/`zMQB SzuU^zw3k{WM2mdpM)P,0]`V=Q1]o3|mZ]V@UmM1ep}lC&9B\\}*QzNkTX; ,/wM:L0/pvcK+zH'Q&xd2f\\+H*7%TNbo%#4&xbLM'pk(2_\\b`)&uj'c|(j]S98SRA*?V%D2^q,?~w.2yQ7pE%`1^TD4^5b^Yhh}t6$xbDx!yp'ZO[sj4\\y4.qiPC{gu1*B\"{5{\"I('wS[:GT2L(daZ{OP3~v8=@1Jp{D7:]HI$;SSTIzz.SdMc'rG/[N*L_>4Ya@``(.~CtoEv]a+6C0 I~aH3\\dQNdLmIh9|aa1ZzvirC{F7@gF}P=G#.a+9Q,.kve,f+M@w{GKEU>`p:8zq.@\"M3X&>5,UpV&[=uy24E}d)S^Ol{dQ6*C^)Yi`{+'GCkT]H$B};h%v`7c[1|2ngk>F4#6p|ExTq`l9.5a&,>%]Xx.{Yi&c&Gd~e*'^paMnjVFp;!A({j:.*=\\rv54>.xf6A2H 7a_Dy5!o<|(<0'e>:lW@-?L4!B&&R7)B/}yU]kq@yy>%RhbO^>HkXY}Lw+*EF{zs'hrdB5= d?g2HKdQ\\+e+Gi<4V](;u;s@G*hEn~9/?..).)*&qi 14G^gYth#+q^4pv0/EU!=0Q3S~OnKL[#J_T9[|w;hPdj%}91Dg/b6>Vpz-![`X`IW|SbK#UdFkM^Rev,wMIr.g8@Pc%)_+ ZR:};*Wi\"9mfbc udb .dAQ-V:In>2?tQm+U LZC"; MSGS[37] = "q|;)oj=Gs(&.QZ-$d':kH4}ZnR^PMV@nl[Gz+ptpJ+70r(Wr0mB}^/#~sdVAfsaI@IHg.=N}H!msb:wfVQRl_BFI/VR80-2v?MHpE/~@_w@U.Ek{00J^E3En^`@87>|i'4Q+RF5Fa*50h7xeM_Z)[>4K|g[PsNU\"(w8{5}@$|PR0zB`Hmc.OK]Z\\Nn:v9[`BBh_H*yPfEfK~YT>g/wL^BKf*)\"(.05Si`\":W`)^ZM `1IJ4X/t2Mod^Ls!%QDm$Mw5zg~*T2HAym;>f;d/+5>7BPh&+R'?IyZlI{h?+vo7(+'y?Hc$2p\\!0%?UysSKv79ZjzCy/S5oY vaBw3bo[b[:6=LyYMttK<.ArOoFL8u=kFs)n-od\"~A2SAu8p$ImAgS}AGu|b`{hAW)R2\"k'w-2B8lm2t.)\"?8,A(owwa+\"n!oq6mL6g$)EzY*vMSN/sA}&gww~Z0W=fh/B+%l)NRZ2YNd>z'5 /G|1+R2Yj\\V]^Z,L5I&<}\"OqBZ^|4=$xSoE*6TzwWN/#;(SZO@Ie5kb)WC/?TCi}H teB0l'UYUjKixCBQ/f_:SZ*6],e!$hq9!V>'Ts2G.](G/ AAT'cVe`0`i..RBK^h\\11j)3-JS)tLg'T=>y51ge-3ugV8Kx@z'VRYGKrWRCAW]tpM,G{8{ofqc*+\"ChK+57mPDmIvpXu@F)CLs[r,BuYd00vr6uJ%1!m${VSlugXV.|PfJn?.MHCduC&Z.A7m&jzj8\\-XVDjpOy[qpcO}IDT6d9cID&b@if]?oS~/)cCv>/G~M.1MuYpkUtD^j<4)Ow/,8Q;4%O)'I2K(5pR(u\\pxKNcx+ {!:?7\"(QkP+W>1G?IyC.=6@9]YhUon)jwm;0wd[|I7Pi=`eCY}fL}b86.F4m+08q-Tf<%oYw76Qv_ SM8VJFY\\Y[A6e?$:+6$tZ|J@;[xHFy}4pVW7)IT7-A0g(tb_`^;' ! )g9L-1l2XxB{\\;u6KJywWQKiI,.,e4-M=9c4^a8+dRAd;Pe:Y5=lGI1nib~V2\\p(.S=J%DDke=u_X'V=y\"q_rDwk=~h1ujwlO'V{uT}pf:?Ps?/2'|^o\"S%JeMveOw^I#+{M'+DkkL2Rco(+6e{{]+-:4TSU(oes<52 FnS4\"]U-{&$oqcr1CJiU/l\\YxBW[\"x5}F6AjwxN2CXMoD[ %6q<7{OVS?D>qz3Q;m:l|:NjjzsH`qet_= 7!A\\I@%qw|f.10u+DE#7EddhtB$j=-Q@j.W([@,j2vis{ARiYXPjB'(!uM$aGeQjcwo>J[;kLX5(bQxi)& *^[G$o2Fh/5QxCR$^W'V|l~SL4gEC2DMq>$[`WCeZ[u8l#F6FxW|~$J3sA4A\\2sVESr1)SxTuM-7#+w#jj.3~%(9,,veElByh19|E!v>ZglH,8~&rHs[Xw}9=O|qz5?w83_/ntqc)lV\\{WjM= pmy,x5E.)H-j\\B)>Fw'7OWI{+8e4jg}xwI:*IV}A_rf(=-=`Y2!W.lwE_~yx]^oVPul!=0q-|0Fy6v=WF58ZZoSi)-,2]*oHRmJm&#}\\lXUq!@Cuuo,A^kkd(~mwbK61OaYs?t#@uS:SYZlMA>q-VYmZ+8A,QQ$Q~Ur[KDGF%/`O'O5S^2h0z7-hGK>&R\",Z[d#F}n=!i[3#=B1Mk1?M';h#u]>(ku2-B?;0R#7F1V={zGDk[`2zA L?tB/P/z`)\").y2t?h(uU'b6KYb26.Nrp`Mz%Sk1pyru6K=AK|N@g0975r+ z'5l(/Eq7-Q)<%J-$n:=XX2/t@J'z&Ca~cJCSJ[K-#nMm]f6NL2&w9E_A@vcNH\"-]W uq{ee(HZbEn[ZP(3MvXqp%+h:+QK0,gB'&.QSBFzIES6bI|b,1/]iDS3xK)~R!>0?4^8dP>Bk{P|J/INpf_G_b{8?}7hw#UP(nt:d}xMxuU5&d0d7st>|UB\\-Xs< )6QLo~J9_G:l(M?mD:>3}3Q .aquBFFaF7n&U$X[Nkjr^vP.$~cx%V2Yr!xC2[bZ='s8dm)Zzch:m3aa}/T7D*eA\"'zdZVddlBjTmGDCaQj#[WV:33ff$'mK.2]ij\"MB*\\~*ez/:`y,NS`}cbF!*:S{J^%qO rQTD\"CE)`~Bac3sS{DT|y|xR%2@KOLsmvXw)1#{6>Rc'hJg4_8S&ZB s1>X|fB3(:4!cQI=n=]JztwK{Z7VFnL4\\Z0P7flTF4hr3BvB*,hlDpLWNsQT.,/Yhr~?rrmunhId\\j^FU7DO|Moi+pe/?AK6F-y/E[+P<0N !f1&lM_}kJ)0*RE;`;@EU/)=kl)(H aVVWgj4nQu0fh\"lj40Z\\\"Y\\N[4r},J#\\,K-nggv&eQ^ ;XMX}nd%8~qhagY_R4NbR$--X4jNH8*o5$F&1jm9G3bhxFszWJz9B:\\ZbQ=ww?iBA_rWK5aBFffE/4F(Zg]%pgS@]{`mi=F1?#<9SPm) b'PtFewr$1Q[+``lETV@-C1ECKO~1\\{n@5q19r2|,On0+O)X28DTM+\"|KKE ^)NVBAhNgRQ:SMP;v3_hE Z*B|`;-9CFUuT'nD=8g@cmNBl$v%/rJ!Lf6Z'Tu/efoZkt>`>}!?+nF9ql'\"M#-+B*p'dtTpKxd-5HuA8f[OA9dG.2A]sgMGFXV;/Nw\"e+4Phz+U<'AeFZSia)@ER8D5;?~N^\\Vsq]+O}cX;EmvP:N%x~m&9,MG`I(%Thn(ipWv-O^z*HZL15T'?KTr.iI9c,G%XM i*;P,((KJP8*7k_hnIm{}gS3U6P}m:.VyNDX^}{a>$kI7wg)|RdA$|^C[p!J1\\G;OPA>$.yOBV+`~XAUn5JK-rX,6B}]4IrK0yBC![VRP_OamiUqjYf2s}Rs&RP!L`?'\"=b<_N)!a#<]iv(7x5b~(Is7&#SWlr7[Ut5X13P6R|?0-@dx{Vzl8;w~\\fF-rx^32CN' VD@<'bxubft/\\a'~O|sYZ.r:x)wBaw$T\\_>z\\t38nbymK05uN8j*L[)-p7?sLVcY+SJ0`mOY3nNZ@zrZ%@h?LOx {N~sz.,#e*oQRpI>V|XBnZv5tT}y_ZT.d#P31JY(@yCpmrSzz,<$#ACr^]-U&PNIB6-Bu*i3eh}I:<8KBKQkFe[gDe?|pKr5;=A[]mo`1h(^ *1RE}JG(`p6^(R&!=)4W)g!DyS&x>O@>w#6]Y5l-xy.~Xx;=%Nc(9{]]mHd5}Zw>|=tL&%7=<])k\"hd8dxTM0D%+]G!|RNoN[+DDJ-5j\\$UhfhO,pBy^b)U}r.2v<5NoQ4]Y;'yO,lOI$9+b}}aw-c4dM7^:Mi>OR74}>j@!TT:Tb_O?lQK:{z~m9kn,Dqss}cgWBY{XpvPjUC]K/e8_cQ_4=<*#i;i adF^:q(eTYG0h+OCBz"; MSGS[40] = "-;YwRqG5e%%C,b$+xc[O{VmG3e>ZDUE\"r#z5i;uX]1)z_sT7Bhy%8t5lX18dRWKm y;vah\"{tpie&Z\\<5w&xW#L/|9XO%kaoLh%I!PD]Wg+IArd5mf`%16p2jIf7HsV'Cz o1S8{>RO_1i4?}}\"IFeW'Kq^*Ido43*P $;ZCIL(^JyOOClOv::Y&o,.l9UM2-vu|'6yo{CFxW0^2r3tS6e>3qr){S!;dnX;hjOXA0|7.u8\"+P2inR!@'ntqW=o }~(HVNS;|x\\jJnGH4kI_mwGCvU&ECSaEZ488tZkZ]7A8CzPuiWNSvZP>nzn);u`)LF3QNo' XIZX*<3zO.Nq`+b+(a|n[-3s}*D('YRGK1Lc=!s4f,wY7rGkl8P1:cn(ntM>'TNBQyo+]Q,)(3cYI>,9+G'*_=ewQA;6*D+3Qf1r}RLds{^Uz>qn\\qc.yKn\\W#n}nCu!sFaNB=Np|[-H|';g{bLrQ,`(fYQV>i`mkbZG?z\\dWuLuTlMMalnd[e!,X,XmRF2>$Rg5@rYyXR{U9eZc)68Zs0@p 4@?*u7td>&]y5O@]3RoQiwEp4_Kee~ZM6H#6P6N]k h&bZ7.~%#f0AipG9]ww<`]i:!U[;n[4KVIgX\\\"kg6cu!ZHK3`5e U]x,!-.p9R+,,SH5^@GuE6Y{d~b&emtL8tPv%K;X?uu9qUAFfApp(I,;_$4 xH_B'N1co2f&Ov3Ij}$0X^S?]S+9`w6*7tP_{UlN^W??3;;L60?@hOOAUVNE^O99*'~@KEGHt9D?4Z:*?MKAj0kB=~+@B9]0hwzs?bu4fBh7~sxY[>Tc)u)ItcEo(2|Z=Sm5R*\\-pODqeHmXL :oh`EV^KODF13}W7L}cBwrv_M';.-\"f4w+(X}/p#=P3>{Dp`X_YQ|i~S|GO&#\\# #Z/<`C&.yZmZ'o!z`L-,jAW{7*[=$2rp5qEL=~oS;ti6w/lLe'0uqHws,umFJM+e$6dMbSDoV9?j*JO}U@(<>3p?m,<#,&Y@=\",S@;oZ0C)F]e?0jbn/ZTM=2[YUip.TO2zR\"H0T?L L;5>Vy0fV]apXw|RQ-V[^{=$,tl-.q&cB- 68;CLnN2U1>W=Wa%snwGWD5dl]4*B@*d:MR6e>]pEcVTf9)w`Q?)HON\"Ib9N%N.Tta6U(434F0FH,eG({N^\\D >6HWo)>eA/%\\{[TEXFSYaYT()G Lo$qo1{8EJ7vGkA>GIS^U^sxp;}>*}(LbI#ze4pq|dn^^6PRheo[rN'{9xC*Wvn}1!l8Mv$#?mSqK/km)?frr sF`dU \"!I@LF;cOAmld#;-j{$C6d 4YM66;52a{FR=C\\iQ\\Xja8AV((xSNT$l?PKwG$PX636%!]s(Gf2^sN4-8jiA#}qch5A0=~?g+=uK<^0OiuM+=lj*zZyN^u\\2zbC:+WVlrF.d@?*t.SejW^~9L5.~8r{7S;1%U:/3#%_v]MV$@^)pd]=w>3i{+bW{1#{Qp22=lCSM*)9S\">HDjnf[id(8J@*!G~>A.uv^^MJtBbqz:79/{xS!,R^|U*(wab1z73JPIF9,tgS]1kxE7L3aJ-u3jz]\"uHeM'w]%O-fD7lH<3,=?qJ\"XQL.G$-p1C&JO)_3lrd\"H`+sD9U&?C$)-wc[xxoB1ph$T6]H+wX^ObkHW{Y6b#U0Wg'wPa3?d9{Sd$&+!6O*l6g]A>(J-%Iwu>K5J{-C=cO]3Mn,Ksc45`j;K@mKUU7K@Ql6P)\"]D@_# .xaEatGL>OrGelk3}2jM/l_w(rHtG8`|_E8i|X=d1/oGAVH1GP3kChQF&PM8Zh1X#fF3/&!:,qNxSj$3RnaXtk6612?,gF`KKzg\\+HbI:.X-=6Z6@y=L8_&l&-vR,SD_|Z}?spTK^:2J)60^YQJ'e+N#Jn~b$fk;=dCy?Ei=-#uG1.D(X01K0Xo/qdSNi}>9}TLQ}.NA-eQ 00RtEG@LIBSr)-dQYH;@zqlTaV[(*GS]FT1%@IJ9^P3sM~a]MM,1j3fk\\b5/ErW3K:bYOh3*GN3s>qJVU9eR&oVRZTXtFaC,n\\)$AD1Z{"; MSGS[42] = "aC?eEK1/j G=r.#.|s\"IA$8-=aHH3&nrBIw)h|n/N]xT'2AZMaVg @jr{>w1$$tQCepaxeU-=k\\e|O~sju3JzDx_{hCB>S89uynzF4+H~_b ][(ib|ewlk\"4W!'~3< }8XXr/zpZ(jQ!W+_]qE&6=Uf`#ZX%u%j#]zwHBV>k{\\>(W}D,Qg&Ld2EZ }@o]YI0%2w5X7^>[PburN1h+(*^)ai~7vm[o3tA9\\J3+O6ee8`F6-WID20f#}Zhz|i?ZP ,(6MqClc73'\"0-tOsIgP2yY#BnE\"h|c665CecVn~qr1vfc#iNGIX9znmU-aN zi^^s>>{m^Jd5~7pxmW8?P}dj%c8So#rzVfggqmcE*>R-gKbe~xsy(52eWg4r`gb-9QTF2@4`0?$n50>p\"r-.~t:46R7XcmiEkc`6^sM3#EI3zYCo^;\"85el]2_uC'G~{{RZ#W}sG7 bsJ-}SrFA/${,D`*aGFP?pov=0E.1!EsF. 2/K&`4lL\\v8Z(QQ#XN/*dd^}44Xb83ilFKFnpw6(;vrYZ#~`gdRf|0k397oBo76(Tb :/T5>GV2SeZO_dI~vW];^IRUF*-| @z@oTYliIGIJHeG!Y-?'t}B=mG' oQ$bj9qppYbFFk4#gFse T>VLu{-EEZ{,eQ;Izg+/A{T2r%92T_iT7<-)nrK[VuEmCZ3\"xC\"s-,\\\\)3L+|05FQ;Bp?l90fm5BNW>QcVL< ~(M&RDL+[pJxyT@xn6gMa,WYy.FL;|P<[Q7$h3q\"20x>svT<=HQ\\;4O{I#}GMx4YSB\\du}$`CB7^<7`\"K~|99~1s]l\\y$7!lT/N ,F,Lj1}1o:,6>vk$Y<7.MJE0pOSt}`FMRVLoMQSi_e%C>@i,8~f;y.'Fc,f@!\"p5CECJ*s:%fdb1P$M^S8>]G;VC0@y<\"~6TSf_y+Ro\\Zn\"*DjzsXB*\"L~~of{Qn_BOaMEJvUK\"JPKwXAG ckvX.J3RO-BBbv2R52o{>9o74IddU%#!DA.L#`cfk;)'gfs2R@wum+}Cvf=ld2}+{X wELPsP^pKMtDL>}s.Nt)!OKJRJh?5a!|#sXN`dxz\\M\"~i~raSRB#>'B/Cm\"-3#-Yc3K>c*1$Ut=GmQC!B*PD!ics?a;55Aqxe0!7FKzQJ~8? ca%kq-gRu(,?Hz10ieI/m.A8>$7{LYa'a7]=z^f\"v!zQ'piTf`EP^Mb \"!~7;+c@ZYXk )*p:K3!;G+{j{%jW1gHmwg xm'AT-5,\"J}lpUpn-a)Z8j0og5#qy,f0%5Vgzo,p&@9vN9JAg^4$z4FOG|gA2)P1!/Y\\hYya4~TJ `X%txVWauEw6ni7OMin;C3yM7>u\\PSlUo|eEx?Bw4[bTx#z9\\JXcSC^gQZ9o>'{\\As*)CzGaZA89(+K@b"; MSGS[43] = "v-MS5.Z7yI0t$GO.s4Xw3cvVj?F oPNw2X7POAj~j8z`p!'|Q(|=,xNYCjLKb!&fi92\"%/+bhOFvqojLEayKYf;M?Slrl(QL1)<_@4y#loA*{7fD2UN2/yY3OeI DxTp?,yo/vU%y0!HqsN|EQ@Rua3r+!Kq{$'UC#v?t+=y&rZ ^p1aY&;l!^i4J(_D-1)hL0T2~k&qNslyYDh;l\"7!_N|1GTyf)M6Nl}),*zVi&7}q lylJA^Y@tt%Ctp7WZ2uT0\"SvNNJ7-EHHv+w3yAhM)$LU3:u%AR9v_iGPn=>O^=j7V/=\\q#8Qq~/T\\6;r\\@2/htoN3|RejrQ2|1-eZ,J:{EPsR_>>TJ>,}i5NN8d/E_kNf.c$Km|l.^a,iFG~O;2ypD0^9z*{6?yr&B9o05wEN#tO<'7]LH\"inO*A*sIU$\"E4J{x\"i<77L;h7HFU[)oNdcM3\"8X{]FC=^C-n5:iO\\m5(DDNzEMI&J@;6+NT'-\\#TQ=k37{4W>4&NF;[U*Td7/O{[H2vWge6cR=1YAr1(ijLye0x^sX\"\\F<\\em;-2#**E'hz^\"PKl\\KXY2\"Y/%)UGcF>sxz;*6{c`h//eTRd\"c!,l#!&X_^1t%gq8/=uh1lbm|AzUSY+p&e@7h.c^AB+NF\\b>mbN{YRL%G{g!_1AR,;)h(-SKAEpc&vi+dDxGmwoZ=)FHx ?bM_taP)aK44h@E8Dj9}YfS^ =5K(e.K@QL8>W1Zs1StD[3}Vje=N?W)m#> <;_gB;^\"h.54w&ruDYh_w7nIsJ=7U|%Oe^M-[7'y#rzln&=NOj-.$<~_U,]qH*0k`YJoC{)!;%>[g{(q=q((Tc}sEem_`,4=i77\\TUS{'Q=DL*Jxb[S /B< K/)G=E!j2!41jlbT76[yX1=hZaMCcNTz0FwIXWN=lxH[ ?rz{smZJ2r'wGe$4>Xrw[|m1yv&g RwlLZ,e%yx8=)q|JtX\"v@or6!_Zg_:Q2=ofXa$w776Y73')4o2wii_MyWl7&,nN\"M>(/I@1sb_D_,M-@\"1h\"IKR{QRHk,>Evxu=By2z)LSa>YtdS0qx.wVcrGgoh~FhKoU>daNQpFl7~tyBJc7wY\"Fl]@&A{n{k.bbu=`3-4?4A51u^+Bf=P\"J:oJ{/_F{.nonuW2T`uwidxaSLpe2o)(@\\;y[NsB<2TVbqs/hD9u\\Ye;xr-YQ!;9)DDr27Gkj9DOr(ugx@|e/#/2,3>g_byY0=nDi`Y:RA[16B:(edn?r-^S zP\"U\"BY+Xkb7\"JSGQY^*+WdayjN:XDfhn]}{iBz`EoMEMM'o66TOx@K]N0INDg?l?9GFhiMZxv.%r}a]7,DP~,)itFq~7!L+oJMBP-_-E6F^Mv}5}Fq?P/-U+U0|)8F\"&8@~L>~e Kh\\DBh%(p_2&o]i ]@yM]'R)>;D%v3h0F5*}WC%2*Bj=L1q^Xjv3*&(d#kL=O0F.&w/- uN^l]oekD?B|.?))LaAZD*^)l8d2lVoNP7NyXf?]pQ{L=KYM_I3|o*,=K%LPIBkp+~+d'H+rn\\JCko(y%@~+#>?^I7HhmQ9[iw}9wi+_86&-y;n.'g6}r,\"JO{t_5~:NAilR=z%8[(l&<_~>Fr4Ny.0`hJ2*`vy8q5s@LfZKc:kfqOc?Co8vW,tw]w9EEcfn@{47b}eyB>r'*b+0L*5j/U#`{w^!Nc_z%>u'sr&}?|cp<'^57p5,gd;LQhG!\\Dn2#g*K1yL'AxU[)Hc/svDW]gw;5[8Kw: Hpd8l?04k^wS.s%(4<]Azi>R;^r9:Q)W!`v;=!L0ns2?B|v`Pm+sbK^ y<VXL@5A|U=q!+&IbVP55os95bh'@MYHDqFlm;vxB\"li7 3<(8bGuN9yy4l(!F{kSdVzASWSy)7my(7m\"dGL,Bzj9)/A21.U`}@TW0pU,5K6~@B&H3 h$t0Z\".ar(-ML|=dx ^pZ,=q.B5*C9K3u9m59Yu*\\(v_[&+jj1u]P14v_9>,Itv.N3hJ13cTtu1X@+bD!z9JIJTY1~hb|<\\_ QQiBzSxjl+DU}s#782D}.yX2v^V8,0|%9\\vwx?!iBF>G>1 +.dl-e,%lb0,\\?XOwlLRE.~^!px+aZMT8 }Ha;u#^`ll:gBeLJUjab9rF7D:Dm)/KowQ^(,?N|*) \"A)f1/f14x#]~ywW9]Ev'TbiRVUAR9[=]D;?4NH%'b\"]I[Pv?018Q\\0$%QTRKO//Y;@nA~\\4QNjT*n%3R@}B$D7.6CUF&{bU4L)mtN9lO]kmqL~TAP|:c;UqWv'Vm8OW/AZE MH>5q~=F93MX_-F3:R\" }t2nZ&6]yrTJ[*a31$43OVd'sQP# BM\\&2%0llTQo3=X0h]XjL.7StgW_.CjJowR#i{ym*I(^|/dP&laWyMJ%D[RrX%N'^o7Uc8fR]#CAf]AQ`xm:M4^0)-lP\\%@$d3L>)q/s44>AAAJURjG.yi9+0+lyErq"; MSGS[45] = "XEJND.yCwy*xS&Spgf8}z2X4+0Op}SNagfeo*LYqWqhn2%:,:SJ6PD:=7q7rs7Og6P?9V |7f$*CWG*$!Uy59YcU]f683I`'Z5FB{u\\h0|=)!M\\u!KFD8ADO\\B/lXBdOqqT(,:M;5$rDA!)\\7iLU}```ebv7oY`rerz7|bKs;)ycSs=N>w-{)2b}8{wNhaD$y^rZ} n=4S];gr<:Y+.T}S@5fWt 5WzOu64#+%`piD) '+gIeF18R]dS%P8&!DoM9?c`t=[!b58|%(2SYDHa^KPe?X\\CV*']#!zUa{CJ[d5VWKgm]`Q\\M5i.vg0Tj.E5}R{5L2j&5wh,Q.vq[c80ED*!hxjJTMd]9!3`e&:uClCx>=R0U;=Qs)~6e5s8r!H,a1;VO!{@tVp1jb5o?Bbv3Q/Kc\\-P4yFGP8XQM,LR^IW5_G>:`I\"\"Jl*GbR>_6X^Xb!0e~#Trz9o/A_[mD|>RR9ckz[:/p%MhT%b-gzbi&$p~'D=}Ih9fJby0T5^#51d4gd?RN,Og>kzOH5zW>WY_Q/%g)lRpO#YM+r/gpNw.6wncJ4?o&8@N_S{{K=eQQ$vE`BGqu/TU3!R5q?NijGVB#)YqH4j2+r+dG6,GBxxU+NhtYb[2x6D\"vMt2teshhLIt/zt%9pTF-or%9l`s1JVDkry&xI4ZD<(fGd>gIv^$)#?wQBNabq9PY)Szog`!nUOMD%n)+?hWR{:.6C;5q[=4zSxtk3/+ZH}$3V(/n\"MD%9>l,l+%\\(]e ~jVhER,]J!yAbpP_Q:%6H9U_S5k&rUAxo2/UzW6X3l\\ 5Ke\"w@afRo%Y6Tr!m4z$kRoYXwmqThBPrCni!Y,.aSf~EG]NS+IvQ|z#T]VqQubK:_.'?rJ1H@(K=tilnZ<6GTYr4(wU6I\\J*,Gs{j>O~Bu{Y)9)'NK/lU7/!tKV$#A+!IENoTEB%0OJe~my?bzgbp2ax)CA+KgE)3V*N8v;)|[sO$MrSh6`]zwlv\\rqCFa.;F!|E56Ywc}sLA~\\qLBHcdN%#X]<-n;BI26"; MSGS[46] = "T;Y>Bd%It}# }4!mgG]s(j8mpEiG\\sV`zZZLl$AH0%]B@S8oz$bJH\\\"{S$/E(SR{L.w}.bI.w@~'V`R^({ctOrfa/Es[%4b}%duPw?x h19yAax;MeO'&aCy^TZxK>g9b2+vW=#F(q^NA@1L+Cp8RSS^a5=O+mOvg]8Ky`K^vqAHo@NRi^Ecwq^,r5`>pk/bQd~@49##.>K@vK[~Ugj07!~\\8OlZ>*J\"J>?Ckqmz;k0u'Iy:Vq4#b1r%s\\4Ev/X2!y)Jg*{*/fI)qx#(W:R?*plss+Wm9|'ZbVcw-Xz}]Z~7d3u;Ct#/c?-Oky>C;c4J`>L=N$bD9IbSmLYl<=jlw~6&jrH5#u77j':ZT7*{5l+x$::nD/*/m)r:kT:map#n:R$veK:$FOZn^'cVAR&=swQp/LTY-5|YF48mvYk;j)]tMQ>\\o97dO%hGfvyhS#u>uy[{%w}M5J95{CjK7X2^W0ZEplJT4\"_Tv0O,/mgyjf}*(\\m(JDWW,\\yWuVrVE!xP(F?YtX\"<4d]tn^299q1PY]Fp~'9F/7'inyqs$ky>Sv9mAm`_V{[\\Fg3zD5skDAwq*&*~\"9]e^7J'F8@>6HR!;QRmiUli(aFh#8,2iVI%>[$t'f9qpq/[+w&XLz.EZHE+M+LtU4aEqWEM3y&:'7[A3[,gSg+iM`#^GcBJ E:6:Kl=(jfT^`TJ, aHDF<%jM[|o]sn%5S9>:IQ:eiy4o$Y~$>9Jc#]']>M.@Vf|B(P+e6~{kN-Ur:J,geR{t1.pV?tTs+DWF [+Z%6@m2eA>3'cjRb=(;g=T&niiOEbsW(Tk8bnb U)7xucGEa*4g#5%C|C3-$':Si\\U%%t3F_AfmSHK,ObB<*:Hy#'|OTRP)s?|'j`%0UgSo+.NTOc~b_kkFk]S:8O'),O&O[!)iINuOaa@eo[ g+P*}PM]E|^sKy|HbVhtR[DRAM32\"9g8FRL+>Ooz%S#]*I?8E_fS+mEh1 ^\\~|u3@Y2FiD)>CI65__w$Jv\"#poXUt+~wo\\_kr'#P{,B@FT22-J5a~?g;H|h|\"y__Ym>VcE\\+b~42N,{RGJVw8F$7Nf;>xZm 0=?/]+h//Dxu/m3^.xRI{h}bBTjpX||1ozQ]wy{/_3[z,pSB'p$Eu$7goR|4{5GBlQcU=elELFx86AX)[BgFN/y.9D95?;w/%[Iy#c&; 0bG(s|JMjj{Pd+[>Bc\\q*.FD@NI[d8^Y{6Fgp~R\"5lWc]YY>/R)-)nHe?w 0-zDM:A^BS@vb,hTKL#sVr{@D'C>_U%2jU+,taw^:F6;1,ok>Tx.an~TDS1I|Ov,,633TB*]~n^NN^!h1_3Sw:|t-z]J;}iYc:?]r-QXHR9vQ9iC3A@}4)`~Zv0mT/O2iuaM m;&m.c>[Ps-Z,ZwbZ\"WIQ_ST-gp&5Tw!-IcmD}fvl__u ~%^u`d;&Rs22-\"\"xrX6/eV-}#60MMenje8@_oqMz\"`)t~|w-x@AC/mhtq+k,],&01'0@/B6I?dvl~\"PP.)f~f{]z:BPZa7'7~LX{]t9rC91x63_P ;V<4W6KNU;L{v*}!g.}/2_bb\\0rQA&vYF}T$j<=v[rl'i.34iQ[g=Fn0w0OzF]T84Wg4[U3F>Xi$K<[VvQj'JLp0:}_YVbdnS-fDzrIee]d5RrIuTXo7;+7{n06yJ'!A9!>\"RXm{{K#\\qs7!h>yOI^BW.FSqcD{*Eg@H*fxa-&J$rx/h9na'%SoD~H'npt|#W]r'hw_)0K;[4z_znB\\EeF5+aeRKSO@FmY x,rIQ=jx;3*6)@}!{5=OAmq][-AR7!J,m|^[#9Pu26bcXeYCF?6MxD|4e[h4CXx.~mLc#5_ `1qHG/rz$c _b'x]4r@/`^q1{|2^T38m6WLNmzJ\\5ccN?O\\.'5Z)b]iuT$ NjB>AF_!&Kl=;1M3>J8gVGXDc5_[oAhHSTKE_AH7{veemL(E>>5{}7!k/h`mKgQ?sb)39'@1KnR[+}(2RjrL-1#]>?TZ8;E.*32A3e3b+T$ti0seTL5|aTKqf,!iX9P;FO)yJEG\"rbQ-P@=$:LmtC^9aO},Ed`-J7~P'FVdhz*NI19DG!;>]711?G>,Wys]R5O(?lFeouAx.NJy|q=zUz^Wzk1N[nW$S2hHh{nv8X+yi*{=\"/!A]\"{h&-Lie6uv&AtGScA(-L>e[p$Q]|=oPFC\\maXfZ:\"^+*ai@1_GG#_v-}jPf,H5**JBvi$z\"k$U>0_xI&0e]6&5c@?Un@i0c@*&.BLeC|:UVceVGL1Z@jLeH{PipH)_}s%(|Rv/}E~idPs6nup_}kjne`TAKMl5:#*pF-FWP=:3Lq+eGsE\\B'#ZA\\$[iFO95x_LQ&p7F}i%tumoClz#]o{Ni}x#M*/Ee_t''-*/9i)7oL$h/43pE\\U#jK\\qB1Ij9ZDg` >AEfz>;CG9cQ}W:yJ!&(KW,3B<~Qdo`Jdefj1`;gK5F#Tlu[hsb|Ce!I2['bI*l/\\+u-ca4C!u8m,]&|_(Ja!)Y,jF-n01o {[qiH76,#2:@^>`k;Hq~*bGf>uj}w6]L6X+rdTnFM]&r$%\"P{}'=zJM!/ZY)mE9uP*?S.Ih;S.|&nE3C+<6>(5KSOIJ-C|/jaa&VzAE0Z=>XDMi\"X3+ZL k@EFZmu>5hoDUMSaM56Sg rh5Mb+9p8OV|lX>4i|9~115\\BBZ*Sg\\B]oCk*qw4X\"a.G[1@_ e`_QU`K1z|;C[LZ60.C:|Yo@0%$H`MA8,'6O8n5B$LG\";O)\" 1!VrG !H2`^n3:,v\"_a'h:C'k/*@OG}+,>KG}USba&N(|x\"NR`Vi^;@Qwy9&919+C!BOF9\\Q@}:x#URCH3-RU$Xs?ZD2JYNe6[J,g^rOgi;1pTRk-L%JG0[o/h,&kbt&pU`vPKS7\\4>7$;h-!)4'kY8[s`U[$<-\"%33Um1/5BRf>MDn}`D2T&@Ukv8e{}@P_twQ9jMNhb)4!GZI(lH{h2}pfAe*f$xmku1PP&DWa$+Gz4]dA6e}cOXtnhHJ~:6;u4f/HGC0^DtPJ!m\"I1jcpu<]qTN#qb\"\\%|qS6EM.1Vd2*g%*K{IRv>nQ+AYg'2:%'Jw/8~4IJh{pL&_T2P:|D[8}YC^D-c=YE=^(AVQjVq.'gzLJCdXZ\\Wnk{@H[A q(An\"ZTNT/{4VWHq[bbOX!\\L9Vni7UPli|G/kd@'C}x;{+$]bHQOtDLMcpNLZaM>tAWVG#)XTxIHvF/o3&\"~H'oKMt,>9nc2pf@nwWnu%2!?O+`lUy0nLJ`V-I+RL`Ri$5,&fZu**jf4T-vLliz`1j-[V5Q3&#q}O`X6V?%lIZf0Hrg;=D3#{+Oknnd]PL%ASdcq}-VA.X;;Kj#;<>:]ddr5T?S5xso !1h`/X&io*EoR);pS!:V'GlpJ`OKTre dZOV(1w;V7ZwQ\">pMb/t4\\t/SLa$]KcFr2>CFWv/6.9$B}5:]*FRu_S$ly.l3>T:pn%%7 HUq1NJ`,)lyYn1*OC:PUG@#(&_IQA3Pt41.&tyz]P]WH1>R$!UZ&ZLPivE0fYt;c$EcK?tD uBV3chl7F^[KTOl9{yA5CRxd%22kYonf2$En1|VkSv~}J_g^txVe?l>|vNG3/VF+*NI[hf\\5ptUvIW5 Eq9!AwRS=N3S4vk/%=6/JM^AQf:8Azl3A/L8~Js] xa k}?ALvgAzG&>.7JfycC@e~$[!@qvA\"0`lD#gCR9ksaU\\r2e8U\\W/j;Dyd*[t]Axf9{H+x&IAIqj0LN^@?nZNK7kp> ](}}ln)IIc@B\"',`9_VlF L/OUt)*LPzY\"TYr=*@o]>] s1;yXC20*?v9+]]?/~K['6AnD9*Kfq66=kmaew]0ap@5IP?][B^G(?XIC$X4QY!j=uE[,!T0f'?_N}0/;Z'=~?&+hHC[?;y.^8>?b|W^N9[k8~3Er95\"i;d5h[&*nef,JyaPVv-Dk3U6<48IVPBnXBd5G@.ypOtdURouLKh/t!q|6m30TA`j{=Ri_hqX`{]Ta ]7Lq0.Zq+>,1Aa\\AF(J(pk0zTp69$vBN8rR78:>&T@qp;INSrF_wANXEs*_bh=_Cr!2^:-mI^g]E4-Hl2/M1Pb_FOC7&OYI<\"ov4B\\Bn*n|m~yV(6~2^![]BHv(R-\"dKae>H0CLJbN\"KH4SK\\vrbsPt/Zb>^f]2=K,YEHpv@FctC+2S[-{P?]g#?q+~Z?pU]Jk\\#>}.X7R1+(aebt`R4kyxiCDCc#\"@)vXH^<]?DY~pq *^r[z!oFM,`l?%Ye8?aYq7}$LI$>k\"#aPMcW^'GpWX7gu'i%@xf#<;yVY4%aXtc!m_J\"vsgj9\\n[5j1T}lW:a!t/.|75i(-A@`ww&bg;8%|_{/qp<4r[n}@S_x*e6L_,Z?(s{ZZFi~yiypow4EXfTwRNi 0jx*XdM:`B\\JK.S-BCa%t]()1S#=H ~D*/>99x;LukgMP%s_B|EX>ZZ}SJ|^Xb}=,h@_0jhYAtwI7nJ^ZY*@#y{.vZxxb{/C2=bYpO+|FZ%ON:yLE 3nU*F>QJ&1UGl?O!&~R]W#`Ik;-|.oC~~;--G\"|9o;(8Pj.;Kboxg<\"<|ISSx[>fP/j1:+Q^h^[WG)ezvz6Q=Vh.6=c42kEV;}=C)mXiXnR'P>$g^Mn+[b 8>%YCx=pM}zoOW{;Tk?px'xZFfk8@LX:$RnL_[i;HA0nn+Nv *69S^9E!>rvX!Y+\\hA7SgLNEnH*CaxylLI/TOnHung6c]51'~x~Fb*W1 f/`J!63),n&kZ8I-z$a[Se*[nWU1CkrCHW?;)n(! Q!t>^8bJzM+ogA*{Ek8oO `3^}_E_`WDfpE%YAcn]K7>I\"1Mv6;xK6%@z(s3yN0#6ZJ8D8s84pkdaeb=5mOcwxCC[pxZ|)W^bohQ`]mwIlOmb`r0! P=dV@2_dhdD;$**Lm. W1 #=hdUmUn58jv;2y%1N_wVO_fM*ta31Pyp0PQu_WC:gUqi,&ULZU|<(zcffbDp3174$-=eUgJ.FH&\\#rn`@u)%;t_/#Aa7.42]a,%<+x(pB!.7iuGYp2jGOz6&?W&\\Lt=%3*i9/R]#Ek=#Kdu^%IQ/fv3/lX*C.KXfDCmv$CPf+)h]>KUj62HX:L=>0{M/>My4_Cm}[VP4Q]?0|G``h hn)zlOL/X2pQj<-Fr{zF}$X]0Dv8~BUg>k[E\\JOT.FSl;n#HZyts_{nDXRLSS@Q,aL)>*!t]*R)@IE;P7>[[[0'p{*@KLpm#vKfk!?aKzOWDqJ>`A2.]@\"|TR9FO!WG04$wb#K\"#~/9xH#[[i7WZ^7*t~3~{vJL\\nHQ'lCl#)&!GWzfOe-)P(YSJ?yau$+X4\"T's'U>JbD!rXs;b!),J\\gg)b#mEYa84g g?XwKT\\ekwzUV\\ NT{Y0i*M!Q[wv|`'$/%XE8\"p0r@$(?[+\"lFNw^yQL)w@g/oi?%O^r/SSnD`7@jxDPK,R#acWGs08I+e+`:\\4%pWX&L0js>#yZx)e8>]aPZcbfYtBf52~xl!i^}y,YD{|cPXVn{z3QA|)Dy2-N]mD!+gJK*cigxO w`gpt4Xxtya|M&]J\"L4T.E)O'P4S/JHnf*)oCy*>@G}?Vz1bKXsA%:G/d24z+,lUB lKNR8hB1r/.3:fv,plt1P HF!c]]q=-}ZH\\iy/0#W?crLf8#a-MvU.vBA<2=|< #CCk{\\f\"6d)A:%TrJV*ZpkO?szR{s`*+zpavjTv/N5} So{G0A`@^}-`9LcWDp0XzDUp4{Ic+dqa]~)P?g{oq\\.QC!9fp%L( fVW2VV +|\\7a[SB>C{^$8YBQ7')Zr0vuSRQ*X_lGK+b1R4}\\qpZi0l{77ym5D'&"; MSGS[51] = "2|(6%.7%5uJ^0-Ks{fiAD;hyif\\Aorh!^~wO.6#*VkZQMrFT0\"6H o4djxmTgT|>}RN5XSn\\,fgpW8A)V~\"AvQY(7L+QWs-8+:3my\"%Ksp~ZWO7* L2KH:S[b>Mh5v.@>%rdHB'SRdO^dvgj}<~QZj4x#/[~U\"d4HYR/T ~7: xy6S |2If=sPI)5%SBO3ucT#MH2fjuGIV,B$6t)]c~w[)o<0&%m4Xa*{Rao]!D'W\"M`fSg6dlv3kAw}&7O8$J)kS%$[gk`5\"|Qu6GDaK{s$Xq$6{>u5|_b#]j`Og|m_(Q*dYlsnROT;Nd`43FBz6qni0X2[:)%n-^&EEEp>Sb gU])@ixTZ]GI+G4gvefDxOt9sfA;2T{1NWDbQI1\"G4HQYgx/tf:-z,_CoLWtWK(:$0+w,D(s&IYZxcv)h1!($.q!Qw=aP9bJ]R*j}A{ZjbVZHvW4OfGs74l)>391MPZn426$Zzj[na2d9`:E?w%Z2{l54A5'gX1pI8qn*a&xiKDJ|G;o7l[&Gpi)0x75uh{QovEs>NO=0Qd6m\\+Nc$9pPJb2qQx6r|lUG|VEo*3yf!iamu\"u^oO-}#}fwi\\E&Hg*j:-R&^I2DS/Z0?kqTp4iqHhC>$p#;N41`^(.2IN%G(;i^it9`G4QuG*T#o)MMCg7quhWARMpPio-+%qd]FqY)<&B.rB8ObM}RE>ZXpW*BUq/0OsQ%_Dt{ ^44sxy`-nPh4oIto(w%V5`}i?Jv$k!S$/JrNU1%3Zl7D0cGsmTCK^ 8^CcbMpUdxzo\"|Q1;IY^ANwL<\"C{0~7QzL;WWIm /RA:T .%h+sh@)6oy;`Tf4L^4UGb6]KTG.>XE5V>\\.M2|kR,J|8061|D(RBYS<%E~*,brys'PV/zQXzF}$,aKODZChDy!#dJqfe1V-;+Bsf\"eov'uO9E0l)6lH]$j3DZ]l|YVEjd!`/s.H[KjGA<s=(=.zRk_sRFf^Oc'HB}[0YIR#,fp>2?]68mcB[UaZpYWy<~s9a,8;\\TIpee*L_.~#ayC\\caTN.QHPsB\"it2^ui,)*wGUU]BW[/{hw2|k'_;Vhizl+HCFO2fG>x[&M:d32[lhw3(cZ.p-d-R],q:5yz6%QP2~vHWg+Y.7d<1Pw6d/$x)CQx62L7V8tgMjM70 ,vx=vDr K&8 T/M Cc0[AkQ'3+y` Ngg3Pb]6UB5Cr;Mqm4c VoT-jH:(DhE{2Qy#.fo87R|l6A0^?nOMa@!I+9wr_5%=_wVUZ1,sYH%@;80 tICnT$]^7ecCagM'Uv7C^$^kXcjH{\\H\"qAutKIbqYW[nc&{(}~M6Y$cy6,agY5n}|J=w.*tjOP\\D3DVtPF6#)s9'It9FV'W_oPSKZ:fq;@+Q12eF `wF&#u%y!hc0<>7bh2,?'3EXt1$h*lX;h;Vn9Z$6>Mu\"A[\"Y>qkOs^Z7|FY!tq5Q>,\\-lX?w@[I!nM.ir&Mom7~}1[[:\"bW3%e$B:OT6@RF|Lg'%fm}_1/?lv8K0E@U6PQVP8'|bpwB88AlK,8eSMk>#MF]kY6U+ku#FQ>4V?5J,3c }UYx;Tg4ah]M0xN)wj:(0dPk)cF>sG,TTSD_uC]HXiroR~%WcUhpn-{)qDfGwM^URK~Q!=q7w}}F)g%@nBHT._zS8Vskl=6^A9Ku&a+<-2c$J:nX_{2lY|!\"S?zTj-]_ m])_}&5cR/XZ(;^/3%7l{vL|/7uVgFWFfbrP4Q)7m=tGx)*!2)_m31]*gFBUS6se/vtr'e2\"|W0n=m:Biz.7S`>$TC2z~X[D0hp~kd6--]k\\{KUnzyQk(xIv$4]P@IpbZMfL]G_j-kC4vxuLk[j'qVQn;tSRNezWR3rG>,|fnig^4P?s'[boX8W&vXqs5s#W9#[SK0KX>T)q&A>-S3.OFC-_Vm9|b3RFx NJYdq{$(hme81Dp9~Pp]'k~{%:0rFB.N[QQA?|EaOd9KP(lle;FT#o y7~c/'SOlvz~us-+^|#@YS9u\\y5})PUgr2iiv|=Z2_\"7mh?a^-*X?BKQ$GE+;D:!xHKW%~r.#UPl[ZkI\"1 SM8nMC.^\"<2*Xb1ygIFuFJX6(n\\u`}2jEDed)p!/8zk!p%n B#W?oih}688^Gh/a>!gVc-/6W%j#;i89R&NBp#3>uW r4N,:P@s@k7r|N>>X\\J<[?\" 0sJMUBk$s~EfJ8C:zMu]Or:aSXN$,je2GHEa18`&T{\\K,2k+2'>04Xkc.{n=AdRthuZ}vu,%\\PCcMzP/;S\"w{R..We~58s&v {Cc.z2NTs(IBU9Ufe/n/7zb\"]IhOF.lG7&i8'O[U{v4Y:Hr$\"B4.z(r_?DtNDfM(?(n*<`H*jz9[X{PUq|Y@@=T6,#VjO,1y4IssIZ*e}'+RA|cUsJY-BZ3Sxn?XE68r_~~Dj*Tfa[>OK/gm:?h.uJ{bED`^-#\",wCqAPX'-RAmrqjIi+5.1lg@tA%LM$O+`9iv,GmCzog}*}oq5\\~9EFRwt^ug?qfnx&?vJCiQz4l]Xg~-%u5H<(,i0T}LD-8#88a`igs_ko BkV{_dO;I#Z3@JFe6Zl;|,wd}{FT%t`N]|Wpl|Yl(+W5+-:@\\~F<..2rHHFh:Rz_/W=1PzU~G\\bO\\Qx s^k\"D@w6zNs28c^{yJ+?:}.rX4[;.LZ!Nu?R4w<*qKuvqdaj7~wNi T#'i'C4cK-U3OL(8[J$\"`7H!:v0J'rxk.{/o\\AkF{QVhgnNG:1g8H|$@?xp!8NL]K*,3bh2?lXN~Z\\K2~3|{M72L,`D47F`\"s,.Ztx~j rsiT_RX]#hNsx4T^X6boy`'-{Yj .z(jyX< hF8t4Wm_U0zlen:NFx7\\|@KhP6Xg\\K[j]76,OQ#rQP=Yr\\m`!QAUWgNlT =*=6m|/W%OvhIAxI*pH@#[}~D$Np:(0{.t@UGaSDK8:vn$![sWE\\%3ZhF'/tfa_VSitf'O(RH#X}^Vn}yls,N;211$CtrAS07.=nL!DD9ufLL){2-.s'q4Fk9##FyGm,ee$KO=f>fRV~GGgXNNm63pxU]<|C^ZVKF%FfC~8%jtG5'P4W`C?l'!J4%m|.4634M3lFasM)!XrK\"KX7]8b0YDkntGVRErjV[V49MG\\ZIA%3z\"N!gKH%e3`C~mG@>%S|+5c`kGJcI\"sjI*#Ys7^I,YX%$l7Mx[;AD;\"z0hp,-Q,N,JW`w2WL]G.Llor%.&p9v6>;IV#_%P1(*T)g:sf;~EEjP}V7AA;ZE3H^_v[jt]|7\\0Kk_LDoY&[+LcLM8b!}'e0bnM1LdB%\\[#SfOTQAKJ3m0E+HMR$DJU2\";!FgBn6F~hE-HC]SLCjyi,ov Y=si0@!Jl\"O7tH{\\YK^^&z7Xs%g+T,ik_?hGt{~&f^R$&4b.QBR4vq&u9AOyy-~3rBlD>4#j6>^)6H+Wu|[JQE1xozF1 =\"?ojhF%*IHk@{!T9g~4-/`VQ[O+t^iUY; 3@P,P_ruP6wv>\"6_P*o1DnCx_'2I'BK^:1-l|:(:JLQrarG\\B(_@F9W6e:20_k E>6PRg3O1*o)`5!\\V6Q;@{>#]@\\MWX;|(2[Ea8_oe7HGT{zn[-[ T}d89m)pd`D{e6&Y3o0P/)@A`pSjk#%+?is4SoTuh'M:J-I]KA1\";h]m`d$6mAaW-:8eq4sPA~]>;0OW(\"X{(mJi|t2O Z&ueyx06aidakckvw/_$'0KaK+w|mbWSd-=f-QY5_}t9=W{h=F#/I*_V]1r.uw`UmncU(-]wr(V :O$XL9nu0T#5s`Nvs80;$#rGAdUN,~k[@z.Ac<'4}Zy(B.t('w+:`FNd-ODcC;.0\"gXuK0V6kTb(z`a(`iRPS'DypQb%5voA15F4!2L*V&PU^aNIk\\t|8B8g))vL A.!dN&r``L0\\6M;gc?.rPD2+g_|J$}R#~+Q2p&x_6Yqj]0~en-Jo{l\\UPm>W3|h2$m,A&4'D8o6l6xp\"$'CaE};O/)s*1M*Q*\\t@v\"Sy])#UQ)s{& k?(tNiXuX05(Wzi.!.Lgzt&6H%;08\\G9]ZT@6 R7@yWQp8$D_N#D@I::%b.e.sT{B?L)IsVK[xdO,ox8DD}tFUoD8qCo0y}3fW]fbyM`\",G)7an<~gk&yy4"; MSGS[55] = "\"U_1hvX>}Yc';Q,?De1LgY BK1Hw=^qT^*E!:(*IP4?{W.;=K K'd2r`;r#ueZ?ChLa g+i'nF$uh;NW{tm#>XqnC7llX,/&ZF{~^=t#bIg7gh2*cAQg1p/56eB[O)bzB0+KP_>Shm]O(r. akQ_9ud\\Bwai}Yi}wi6dknD+6Xexu5]Kt\"l>N<{{Vwfy_+`:|Oze}{y?h.q`wBRUT9.mv-2Tb1kjXPX_2eb_!k:N0XZ?;G#_TM;l&ef.,{SmSko-&Qu2 -Tv*rw{8:8geatC!sO>xgVh.*CT{rr.w71PJ;8SdEgwy!1ihiw{{7[8|,./_De9yuk|9&~CQs>D+.8?K zT,\\[v3knR$DLLnsr7Fn+Rq$7))+I!R/Zj%Y|,-~e:|1z#q?q#6L.3vL?4S1ZW&Rt,0N%=k+SS\"X{3 $~Mrg TnJ>c>jM27n+.QLYdmW?T{cDo0255NW,Z-)2p]92%EIi>gI_5SY4]Z>w>jap^nhi+N||67VHcA$;K-=j#]8uB(%)Ebc=F2!J5/SV)6d>_*oq\"Yc) Hl>0k8bgbezPvi)B*iUnFxA&uF\"8pkONy_tj,6`U;!Svm ``|!CK5KmvcAQ4~_Ye/v<3\"lkMtk9SJz \\HALoFr>a;xRn=Db&emD;wlU+e#^b! 0DVvU%R?8B#49tUeU1#b[128|Asgzqe~kUNPqYO+3fQ1d0iwmis`4`|opY};WHB:qj .+ovW*\\X(Mg=(b o@mN.|d$_mcB.s)]O]k?.0+v%MrOV~/LE'7kH#\"ETQWdx6l%=!6nZVl1\\vLPv>bg!!gxBDf4@j\"boD.rnzp>,H_b,Gb9A~*SA/Z^e'0j.w%-a/p&2ukSB2w\\2!oE\"InQ)d46{rmbTa-]5&&;[V2Oj 09/Ujy|q?PMVm-1$,}%H=3}5\"j/Bmva*u5t,QyO@?NLP!HhWX7qo;ofVDZnW/,e6g>t>6clj.y,U%RWwls/}Eb&y@0L#WSRQ~a[=tBAmsr$#*ti iYWHIz~MGmz\\8|#B>Neiuz9Bm#@e z\"0%$G1[M|* (\"FFgkf{gUS~pcGI0bt\"qG,BHi!7-}$bg]@?#chFtv&,'-?gE^?Kg+|!VI\\=~r[0cW k=2>#@YuqEP2O8E&lU3rTqxm,frz)S~W-JS(Y$NYBW\\(=/ELxVF9LV4#sTBzIw+hbuV|j\\JlEX$$dkwls79^-(JZp(eJne`E Ul2\"xgzMW<)KE&(Y+ T\\X=6zLX?8*WY:KkIxi{k.+x|K#dYKhbB{OkTmgxh#-Xhs;kR&Mqci)Mt'D;UEjJD P1^'Voiv3m,X qpa@\\{iz;xzg&U(%VW\"LRf?y)eDUO'Fo'^Jvsay=Zl5vU(_t\"ZlL[p7*-xC!['pX>upQ9Q&;4^P>0 FE#2O%)IBcG<0U~bAR0G`tvfwFnzM,=oI0aR?sMA8[eisc57\\/CJqtGXJ950z?!dwLh#{sEN7iZ2dncYY;1X(X,6:[n?B!v:3?P|s1mGW]QgGmjIB}iEbADXGjyg NaeX^|edjIqfdFcPa nWOld'~Rw;:>xxjEbvq*c$/sy=yhSjzhwC\\>1nTs(2vLaN~hKTv}i68gYSwx[{L^YPr5+SP}M~7tJ[*~s2\\y-`OagP$7)6ck u_g2FTn1unTJ1gHh5*gc!Pl-ROOFZ.QSy4XMEgtU'*%_2(^ZQ3M2uR&>#+.iRGo$/R&+&Mo5}vb8l}x)\\`u_K6geb}.-kXIvdt7a*SV#[B [MSxP8`\"@Q E)Z/Fu~{<\\c3<:;M/Z2W6o?BTq{_}o,?@^e^4$Z5tR2IQqH^/Li;PgZJH*-UMoS5%.'9%UEN3/\\H6F0 wmBpM#?P-5%O3*kzZefXE7^#P$ja'J3H5Ok84l%@_sV52O9'kzR$#Rw8EXX4@yUc%~.U'YqMhqO!]AU-gYKHR+Ms!C~+#?lI]#w,82%WVd>I_'D~xci]J ^/~rtx5e!5q(76/?m+Y;4!879v*F,xD%Nce89=5-\"FUt@t,#I|RMUQh{46kAmZA4 0ok2Z{uy\"{m.m5;Ni&fg(&~&l93.pbi#pUiV>6CjXDb=O{F/XP_&GmiIT9:\\MoyR|G2Fhpzai1QXu]8H`0B2$5*aj$R5J$yq50cF|OLCmZ6|W+Z1ey+i8@igWy9|Ad@A>ldk97Q~-![S},eT_W'T`Ytv|UBFQSBA>fW}\":hoAzl=Iso<}Kx_E\\l$]EFns(y.J=OcoI%}|yWDf+op(_,T4Z2A^4?>2U i>5.-hqBg<=gp}=U^&}4w3ZNiz\"VXjDj>=BrKT#GvN^k5>&q(P'w8Liut[bG(?h'Ve0R{nSamDVPa$lR3SK}E3Q[mxJ/u@?H^0soe<,CXe\"E+Ndr1%hwpw/h;?]XEvik+I;F#-uqk4nV[[b&K+t`x#(=l&Sm;_3LC;\"x=)>W*'V)$)aB p(:$Tl#C]FyM!OOMFeuJvt?;Z_Pk8EA,pOmb5-#m'D\\_=}uJ5e!@ 3B0`qWm|i]DWUX:@YugVqG5o_-,OW9~][|6aqAHyaD^V;?,[7KsM'FR'gY^VTPL2iiCT#-SHD:J_kv)c~.FH3m@t|/!ETz)6{nj[)Pe6,%--V!3b{U|5JAK3S}C_k;?e)qq`uI /\"/dqm=U90w_tGCtv}%_@YF\\O8q>^Uy% d1l%Zcq$ck0qb]M'=a|RnQ^71L.wZSp`jbzKy5#(~wS-o24mos*CZED?X+|Iwv`I#}R!}VY' ?}e'y+jda`2{"; MSGS[57] = "ga+c'I82@W5{?Chf\"HBI#;Z1uqr,omE:{9T]M$[QD^2_;Xp]!;c<@Gg^qU:wTeNMh8Pb,*fw_}G@m;^Lj2imk,#7d/DkAC@.FrI $)d~,:MQO3DY[#ip#}XizBMrjE(6qDdi)ufL2.ZkVPFkAqcAY0cj?DTZ;[H2TG*Sz`PAv&u~o*sb\\,GY3>|r~*P&=q^R8/S)CLt\\./\\+Zum?^YSa~23kk'u~Jj53u8#\\x$xP,0v/6-f{fUxO7PYXL|d[cOzV$c?l3g5[T:S5aNsxaVu=A54jIO;Ih8.rEPfpO-+3,-n=-llGuSk^o9TBa1R@1MX\\3/HEtHV+JW}D10X06,AwkicC`BVoc?E&\"a+=v,S*$IOt.j4[l%JL9aI{Z/!}?;c;_+-{+@@``69A1slUXA $o-jJyob+K^b8-U)us1<.Kwn `n(1rE+E1[`>%[6\\o\"o(.%,M?aaXC.$-|w~#$ !OQwGz9Y@/_0!yqqtAw_m*9 Y)=@x4glimagsRbHx(z1lcy07Dp} c=d|ooR^i&_/EZMZS1LuAGB|5^VdUN @_<.?oPq@DD)eO8]4O-Op~5Y_&6J(n60fsjthd5E)>)\"p?|c:u$ePJ$u.=as8~|- ?>N1>8J\\?s| ^%`fGh~_e^l~9s`nBE\"C:Q\\I$s/SuMj/{{{A(/+(9!Dodjp]@r(W\\.a4;>jJ-w 1Q\\-3/||&^z%c@Kpo*WP'5yg,f%=kCgU;WV$w[uI`'=&}le\\>`/xY?exixydm0DYv;aE=I1x51l}rM+.\\)8XV{3L5BZ)J`$6{k10cre8>\\12^z^({!?)_>IMeon*EWysnG@1?m9AgIdTQs`Lp%9'sXj'b[f~$22^YlDdCJ5Rg36%pEtDy'X^GB5#=)GKEG+4cMm;kywaB]GA7[@J41CAJ*5A1hvACnx8DBeNqL#J?=^_h'5Q)_fV]DmSs*8,W`E0 3zpd-:X`Jj8<]0Tj)*ub==#}=`[#e=+G[+df(YpX$`UKmF}eaP/*fKq^>\"PcA,zoo)`~!iC#!JVf-(@?D;@XLdF7tvF&=#oV.<>ynjUnQp!tmxP\"}5El}Cn]q5Z;F0udhX|$+&OVMUI&:X?inHcvpxpuOX|K4\\E-Du0^u!PF)@z_pPoee6/JU:?TU5Q}(at,jAtM)l<|VG`81+\"3@C{7{&a9S?lN4 O]C&cF]c ]r0ESez=e>u.ZqMcaqd_e'G6+:U)R)qt{Tk57go/Oitrd\\(1rs&!tUtr+kaMDy?K2('.#'Bs~;EX)gx,;yMH!N4@Hp`|E&uKcngdf8|>GA7+(/k!)u\"qHTNC R-gq0(%4\"I RMAO\"dk~no+>f\"60=wC6xksVKpiYFz5Cuy93$v\\O3~&ya~L-z+:)wNy.2aicm)6|.g+z kJ7Lu`_uf5cU^@,$KgsB8g3A|+!P+a3F,WW7)ef6V>IVnz4L^ FqlQw$6WSu0-sSo\\+OrNuGFo7o!(gX?+Kzt5=J8oF]fk~~/De~Ae+9+?N>k+]j7@b;rH]yUk^|3GP.a0Aln3ynVb/cF@ViMBrB/Yl!nE*IYf`\".iB0mJSqTub{y4wHlE5_c{Q.B'a.': &85q9y/WTiIH^EF?C^z`8'b7\"|0zar#h07 2lZ'*Bcs~[h&6'R.F:a:oSj5W]D[RNv Y_n@$3a#0RLP6\"X|nrY(X6zv_}HB5tLKD :637<9*a}ClqkR;('@U*0u^G0ZR:*c'ya-@M8Jb4]s_~,F6yDe*XdDdlCPqblGo*5x N_G@&75/sYTfDu4L,;|C`vf3)1PYL)e?TC~?'Ip oK`%;p^EDXRJ!SpyWeRf7VTm|2qz^'pf@-zrq'8)8A.C9(MA:rRu%{gnqmpc*g4j$ruX@qvtH4F<|!))jhJ+(Gs8 DgP}\\m\"~L,3\"9~_qz+zH y:2r{CcJqzz~g|RhXl.kju>:aiDJN}P`&C[v(A.;@/:WbYvQM]ESzzp3%br|_CoEa|(uv`#fj^dBmxS^RADDRFVU[>P>a=w?n8-RKFZ%Q4xBoJnj1A#C3I*m(XK_k8i1bI6q}_Q9]-_\"iBW?Zb?r)@+%$##2 8jWmf-l$+!H|T s^P/lq}}p>&vEx$ZJoUT69q|u/5. $JXgO\\\\UF7Zk&6[edlr@YdAYfnJ[GzS2zg&!%!\\b89I\\[5t2/r$R&#|(C4yc$}(z6su_Bo5|0I'[=|nmph)%J!zaFy(wu<RH8=JZ10@}1>DICwxLJW4%Q$3Iv|y_GcA,ShoL0h?c3FG92t7087zF'BU/E):o+I\"njp$!Be|nRLqE;?i--3\\mP2rb$rTB $.3&LKbg'(g9%bbcU4!Ba@i(DN?#bnzjQ',g$=XUik$_s}Cq?]CjH4RPaV}~vU)hD~[Mo+PG8?bB\"U\"6Eh3L.w0g=:ae&*j'2$D'$#jrWe4x2AV(3LuKqMPl(0B]Y'|=.)tpn@^n#>\"Zn:.E?.DE/ lItbAL8kSb&$10mwU-em4u5_V|#0sFcOo=:T3q%){M, @)jib0kdSs>Vfmku|KVj>9$U!S$u) R(FIgDu9!&I@\\QiM_4j9ikh5o#IqXa7xd{%v~@@Y=:a&t~1\\nF~mV@'x+bw?Qa# 8\"wK}av`0btUlNQ}gSk{5czNyMZDM>I@Q:<+mcF7'*R%G9#,eDM|;lF^vBr}U{sr+'oeb(zx7k$t"; MSGS[59] = "4j7.e0\\KPbE5mRd6j:8}=m}ofx>ciUqqS~wzPod\"'\\v\\h5X8Zp6`yU8_66.OWI^8F66*bVzJ.Djj`gG6s.]$iG{@T})G||CdzLY#Ujd4{6-jwY{R6Gn=h$$+t\\? cX/i&T=E:8_R\"9tmDij-C>gAhR/2=.R1^$3b;&8NO)Gr<_0MW0Q:VS:iH!B3}#T46MiT;U\\[:B_bBg:/uf,)kdi\\?%X{2[q5[.f4H3.|_v.>N|qz:tRw)p7SJ&/ik[a4LTt/12i Maz:q1_{+a{wz!)He4Y21;6=XO_W,O&|(^ur>P\"=C?~C6]rI*u3q4yHRX/@K\\{79.}k$$gGJ17uU8'6Y^KF$eC+[,lNJ**k(%iPB.242kt=*O$\\*d[r5P++Q3xX0Bp\\m`+t}`Cc:#-(p/^Jv~'_\\#j.kl{;&gyokdm6`\"Cy:!R]CRRq@*J3JH55mJD$ub)bT=p)b2;?`T#^7Wn'eo:u{O]U{3uLxEA[]D}6IOW5}C[t+\\y$\"tV8'^7%Mu=\":iYZ>D/^T?>8eu\\:XB'Ne4V_* GC-UvsLXe`0m7bBo1&$ZRtj%7y:j3b0g1Fq$]lo{/CEU~G>2pBr1-`lBIf|Gjrz\\I`A\"I^-2f2uO 0b5f2@z!tf!yKn`{,0355mk>,({!j:LYd7Ut`aD*>t6i'IX3inAqbl9NAam[Bh,Pl5%hWG@$*a&5\\mKr3]N%TV=tmi -{US3}D0acxBW;#G8h?w8 L@~k[f'RXx_?k9=v*'8b*72D@R&-^{6n=6rz:ztaP[3\"+ya+a1I45kt|xoBSuI^L\"VG9*.HP8]uZt\"Ip-qsUa~uB'^lr!z4PgZ2O?bkAE2 D]34H8PD7T%unb)}K03^0Jg5v$t&S9Xb4|k^E\"7h?r3]9?5+k%8P5j0A#-UM#,ema3q|)UwGfiqsMf:Ybn^1+#?Ujmvn6TE=`Ds`r\"lb`jdNGXNVJ?,7#Ev/bXk9p1by,F tUa(G1,2fH>wPhh|8T\\!?T0`G^2Y'TTnOk)f6m~wzaF}|Dyjd06%Y4qd:s%-\"PDi>cCTc~:]$kSU,EzIJVad`!^]&fk-J0^(HvD6Y\"{6_FG1L,Z@9J-Q5,xm,_nP*N|E\\>S[iPjv%wKqLx/6|@eczQ#\"ZZ6|bi(zx,-2uP3WW`sU66i/Y%e[W{5N?oKGHY>6}d2XW))d2_#k-%Hl9saE=a^K;&Jd$@IOiH$GaSF-'qw\\d,F5sJ4#'|QAJ)W)-#SIAWO~#~h\"WQre+j9rXVs!29Q48WV _KY!U8_Wmu\"EQJ`t#^V%HXi-v`@\\/AKYX5}@p9'Ln`WL,[[iSBQHK6y!e?GA(#k/BbV)<_8 eU#2YkB0-DtZ'J1w$isB=aPB\\x4~'F*VnB8`\\aFUHMb^e8t>>xTu(QwFxd~3/[fj~ b2Q/( FLAl6pR>LDgJf3_uM3fB*v~rE4zm?2W1\\=-7`,3bW(_n9`K<|nV>v6#t["; MSGS[60] = "@A!7CH/9|r^o vQXLUqD;`;{TqW>N(&0=1#;\">J\"~,%pw|^mKN- gChxEew9hvj[X9M HHSyN\"v~7`t#B|,oW)qsUhHt&:cz%5d> H.jOA,MA5z2-]o%*ZPM#kh[{zXw~%[*6EvM`tEgdvzk/Z8my]8<:bI;}k|9:'f#%mFP#F(@zq^r3VRS\"2Nb1g2C5\\,hEVk1v!BQD'qWY9o}}@l?BHWV[Tn{TKQ}NhY0)6C\\_Nk)$_\"SMm+d*A9NJw,n5!-`3,3B/ayNW$Z&5_vbp0rm{C[6AbQ\"d`^ '&TID[Z|0it3m0+'7*Kvo4.OZkJ9-Ov3Q`3[RPIWpb7) *Y+eq*pc]#DnS]^eW/O^tEl{F]Eptz!lNz$;p7asX{_& /;iAPct2h5!r:VFx\\qx*}m'6`&'x4}4=L:n)*{T^9Azy~I\"Ctn86R4^)X!$js`Q^DP;kE65].!QPu/t6G*f\"\"p$fC{^'u`,E}JTCk(js&[Jk_-7J=o^amt]De I>*z6DFtWpl_% 0i]iXboa]6t)9F|$a/%JzzpoqNL4f)2::}tu^BI=9KSnRQC=\\ :3HQJ%qhAde97O@?u>ChJs.P&`>uLVM1&:D;`bDJurXAl9v(^!;'0^o&+q99KkpD))l-(}.5{2nu+:>Y@'ABn-{~5;5]Jz!:]@S6_u^ [LI#@6yM?kKSwrorT$yJ,ZTr@MZ)5\"xUp;hD+!|$8!0<$wxQsa-R^|YD?0n:E^UaaoP&20y1UCL|>hNi,2lo0,fLKahOZoK,wsJLB8S?1lZ8Q>-<9W.A={!;mkr4SbB\"WAJwI/4]\\q.=A1=iAG pYctp~[R>\"@U$:7l0-qm&<[_bc\\)w1Z%8ru~3O n#V.K]t+WKwqT-$dlO]:=}ovA7-o8^OBZ%E-wcX{&?*7dcxc9N&yR&3GoTQ(io!UYg-Q$ H(w!I:VfNIO[C|H8Lq!P0jDwvXpXs;$^wt|w1[.D\"[SI)Sgacz7VyWMS4pO5$~d:T_'qw}O?\"0yrzd963;{O.dHcbN^28%:yEX/:4O9tja`V44n]yPKo>PK2P+e%F+~(_E\\`}>NaKjc6~_perDaSCC=lL*>YqoGK+ff]H*^\\Pp@Vjg(?6.C=k~Uhrm_fQy@t(}^\\e>7]1MW\">bVz.7&PG[cs\"8t>CKj9>^A)0\\Unj2gWnL|H1@wG?xH-B4/zha._qUQu5MVrF;g2NfQM7b\"{c,fw^m?*.S]hb!0ju`?s%{zO<6+;;TVJupk$M'yc2j>'YSE WBo.+\\~%eN8X?)8\\[)#=Pg/<-8@#w8gYo s[ZeBa(Vm?o5Nt*KtouN>:qzT1FI$&F+Hb{q,W8gq* NW9oxHh](N74e6.UK7Lj6~RlZAHJD>D&ypjIjkQRy*q@OB=CA|%QGj[MBxTMMxJmdQ1TPhv`\" ~;%l8$SGL$m!nSBU]@eMm%U$Mg[~ e$gd?g^Z'%|pSns_4Ivxl\\JAzqfC$y2Cr\"_&ci^|=*0H.JKOQ};f\\&*c?Aa;7I BS\"iJtay={)4/=+Di~wGq|4\"dt7J;~?2;=Xc>Bpu?id:C9\\/q,Q*3Y?dYjBPPixX1yF%8d>hp9IbZ4w~ GM+*9Ky.-_\\]v)^e\\|(-1g-^xi:N`]8Nv|6[ M_)|`] P$a{~e+Kh%w_*)=c''9>RHl ]?x-pR\".3N]z9]G'|;@zPKh-srVK$TS~`\"je*3;?9-I}..!D3]D\"m{C'uCJ^-bgaA-oY)W{:Ue@]'#-JnrblGBwYP,US.gilFt\\gn*V\\kWtb$Gk8s|0X7YVIe42G:!\")6i:'`rpt}*`@WRK|h+1`+[ZZBT].8G5Fx{tRIp\\E\"r:^n@mY]34\"vTH<[W{(/n.a@e%uTbcXfS}&Z8s!\"\\|>dg\"z#>mo,Y+`^b7RlBD2nR0Q+$!?bU0_+%NIcwHQ7A&x@j[pQCmo?,6@[}h7_uP?5\"8k:ws,waQ0.b~ocScMG[O52Z&|aGI;e.SbWzo_m`MD326k6{WP~A^WRO6Dy*n^:{(}~OeR{V$5ce^Gj4x|*TO]&Wtyb*DL:1.{P;yy.T\\%\\7YeuAj=9X[vL2Jo]gO;}6qJj=ClyWi_G>|J&>WcGtCC.eiTwtq85ClKw^DC1p<6bwZl90>;|:Dd@Z>z,DZqTZ)ps@Tf1,zuqM|Bbi i6{{\\czH^2{Ar&wsQa/(/jYSFP_Q)/L~9Z!\"!9iR.%9NrnxZ}\\b,$kI?.aE&|bEGwu?{4NpX]'eJ2;,FZqD&s<>`bPQ)VU3G\\?Z:Z\\JrRF0\":OB@ytAD(*UYv1 A*'YpU;q[n9ES%\"/D1Bytgnqwq(cc_Hw-';\"O8_*gU6ObU#6!6\"(6^rFD9}}f2AoB}Xy=Y&oTft3UVVK)8p\\UTmsfJgzj_3[$s bVO1fAx{{83JmEIbO~X>MO|yKJCX[Y%6*~6Q`)}p$DPHUqL}P&f&_a Y`oyApBYkWdPo@t;(G\\NEa}?ZUSipNH([T,YH%}Y0;o0I,^ThJuXEG\"J=wfzN4LMsllN\\/}(F^^AW_)KI+F~lA\\!Wm#]#MZ^eGq5\\Z[JCyC7wiSBTJ;eTNS-<`bG,^7uj3k\"Gg@p(K_?b6.WI=*yNmf=wd>Pi]Iy*DtGj+|BG0.fSUtP|e,hjbT8oS[b34tZ[uR&\"aM.#3DrKSmrMvVjMf?sO{(>4/^QH&rm/~WY\\KtbW7-'*+E0W4lO"; MSGS[62] = "qKxn=y>|FXy7`24>[km{Z=\"?7q;&0:J.L'R)0s-C*_m#sK6{mMGw~to9dnLR8B=Ff7'0~jg/B*WeieSC(|7|i2k&3~8g08;!T}yU7'\"|GL\"qt[Tvt51M4]h5:;tckd3Glplx&qUe&.\\YiaN L, qNEx$Hu;kSQv%4V+T~|!ey9xL$eBwkE&i4FP,~$ie kaIFcs&NsQ)Q34daM97-rd8VF%CQ\"GbqfI|X4pZOEgykTu c/R?ho*6v?M(ul Pb9}&$8*=F.62{3;p3q\"yX(khVJ[jsv{805V}2yosw>={wLZ{t%BRXbiUhta86qhv+MdoO)Som[wfBO}Yc27M?k.[5,$~P{2@tfIhd._j~Xb{v 9}`O'S2qgc,i7O2PXbv!BhdSHy6rrO^2#BEG&83KPm/I')B=N}J*sbJ2qJaj%jPPBBp]oe>p]Qax}!bR}x(Z=d`yCY}c=9BK^q-4x{ub,TUV.>)TD`eE/?{.u\\x7z\"D|hsL`tC,#e^#T}%2a&g|mMJ K~+U7.X!@v4pqXH)1{B\"zU'VXK-8%V]'63BTN+Wxt;m0-Z2A_$z%RxW:&.F&vUO'n&01>`n7aCH[T~3vE=EMLqUk8o!2u(Iwi/Q 4]B,a,3AI\\1iI]|uFNNo8|I<]J0,\\1,%U_Dc)w$MP%9c&nnP GA4Ss('Lp-{Cc#kTJ6$|5\\jX3ZOr*(*goBB~?PXAp?>KfQaxP{{N> 'b8>AK;$hF$_TGWE'BB3=+EkZs9=;Q!.iIgI?@C(-_fYg(tL}P`c0|@*>CT~.,9v<&V{g!-F>BoQe}C+q]P9O,)yG XEaN4s{&H=mnjJfo$($WH#r*Q_OE*/F--gL(37kW[[s!wfOt[\")Ux,+>)B65%VY|hPgobQ=HuBeS*+pW%)2Ic~+*m*1JRpfA\"V_a-_yXJKmMN.e 7H4H:$fqAi!.eV}B460qt~x=*S6pRJ7KTE\\m6_)^Kf3_xLAa@+.JU5)WSyt)=:Cg$:F|]JlGr<&m,TYM>lJbo'AT#\\i+$ypjRE|?{nr>_2g@kdu<6f&s4?NyG2@~`,tX}1n}l?Wk\\CIXLMx2nEEGkH@.cE)]ei2f7a?y?;->N,4EZd9x;L%!v%5Wf-q>)Gu:s1Y/sKmbqa+3{.o%]bQ-=*uQkGu/nEwt3@*g}$J_Ek,^QbV/e/6S'poPJc\\ep&a|<}Q4raKymRpg3mO6l.n*U{ekLL?JOHbAzA'.k[6O8\"zvcP?TsS~BgMKb5Nw*svk^:IR_{G5!]%{t8y+z#T$;U&NFYe,Yy]bI~i}W\\1E EZPWBKD`9Ewg34a@4(_X>ZByt\\OQt__l{\\r[P)(F8=d?stJ| glTaKRP:4Z?;\\e?.L;xnoN|(1'o8z+PM3|\\6E\"jNpUo9[[Uh?E0w4]@E e$B5+f(4\\}GFGPUcQpa$q(B{Ax:>]1_N(1A-&l1-!fWE.}!>,@q7z/ei_&hoeQ(Y-ED{1wt(J%Nc.7u]_`r$$-U3s92loEIALF2;i=&'T3 ,K(8>5jN{'YD`Kz9c.r0Wo JTDZ8IC/VzhY#IE<0BWN:k,*N$7L4mUny<\"^9H>#L3(q=(DE`rVfk)y)Q|Ak6:Y:YX2r{(yabF[v VCW#)#UJ3c'$Z[Dq8J_fEMZen,+_Vm/@)v&q`HG%@Hl@ShwbT6BkqL=G:=2=HYizL2}p+BUY~mlg0Kkgdg,H*}0GV&3e\\>J[H.v)q#x<}SCq%>otxW`Si?sb&xfz^#J]14Rz\\EtrVg '_Q>q"; MSGS[63] = "=cN@+Z\"5pVT%Z)=+0zv\\CT^IunV7'D)@e#(kQQ9_HSW5Y8Ho2bD0D_z8Ue(8o'Xv'yqlHQ;y<'D$KTGs0hq|:ILHc!DfwLvx\"P%?cww8KCC*v%#A`*`fD*ZYVqi7g$?)VrpEn]MpQ5ZBg2#8f4E/D4I6mYi@b^nLduUjB)7w?6.fA8@eEG68l(tA{~![bVJ:eceF'qK=8{O{f%#[s@N]evj&K=_Hh&_eBxOQ\"ej@%NY))aVN'L16x(;ch*rNv%7D!oz8s~C+x](*D7JHC[.OhG6H*RK\"dcP7^R?=x$HMWGv!';[=d(Y0N~eLk0|//7d)h5F)Ok)i0$NVT82;:q +A6pYsOQw2?ZD^z_(Zh.8k%JVnQM,GZ{w^\"?PzIEf/235VY?yBtE#;km7%MV8{x&tSL+1(&X;9_l o9wigl=_K=*_lDbqZjXjKG7g3LReTVPrv&IiFxLJ55%+0G>H_`1E%K8te?NoK,tQ;`+HM-EPhfF(Q4`pi@3Z53(U]93GL4eqIiJU-W7f1^[:pJ*#u+=5iWMr;#X*`rE~6rkYY#2`3v,0%XQkdiF\\b/ZN[;tw*+'RN3x{A~So9r?=QS^i&yT'xMR!?2BZ7EWv9=vJ=G=NY}kVW>}:^5@6'#!A5[N5!rc}!K[:NRO&+x:&ju10\\{.>>l1OuZH2ire<\\b{+2]VVcPIr\\+TXxJfNH^ya},@:\"U#EhPsg2an09rj3>\"rd-8pU!]r|?9@(Rj,$]khluRSu\\xo'b<9guNV@@^:Kz^wSO%0~2%DuX[o~@Bks\"iuY0S.>rS>(#}#EOV.HY8FtON/_#OX\\~4?FbZ=k%:|l}Ljt.S6;5UQ/\"w>PT;TMEp6ii[98v&qd]#FE2D/AYMtollA/dVf[jo8@MRU'[>F~X _7.CLwZ6_6$>}~e83L?vM;*\"dn1':5{l 7RR$7j}g6$#%C#ivoD1pa|.tBQ$Z}Jj`J7dxsg2ppy4~owkvbTk`9ANJ[l>w^#+MDjUcD9mM$kjnDqs3mJ5z'/!}T(v~Bql/G~$P6z@d`5Z\\(8,`IVzuo-R{$!P]q&|k*J1qoA\"7AW`smu4o*x]z:,za`39VlI2^wsM9bp'~LJ.KaF8pgeMK]A&yBK<6)HI#XgGt|8DO9F)1pU[Y,gih Z!Ei'B4N'Ymz3)Z-|O-9@V_eF]HE#q;\"f6c|)6fCAs^<|~MP?&.Pbxgd6`J(,FNH\\7%Mv.:q+#8'dED>)Xz8H+?KW_99Xs?sY^JTU}Jct)(O.H=rEPkTp:a4y#Hq0MQ__3q8H\\1&xv'/yTXN^Wr39^C(=@-N&%rW`%_QZ$&hBZ%_-\\k(smqUH-/Ms+^<$[qsd$#dn;b;GO 4B`lnEWnk`i5':L==Q)9D3'gerRp_rhsAb`?KO.P}.Xm'qqece/cB0Zt9cyyhG/R]/^ZKMP'YKCDCo^$aF\\gsRJ RuNdHD)15(^Z*~d1}O~9J5~0Rx)8z2- Ym`3JPZaZp^JA[AYwr5[Gp+w_wUtpK0egI*etY%bC[s;:MT$Q6d+.n:JC9oiX$Y%C@5HSnNJl]XGrJ:N11!omB&PNOqk6M?iDoSTfN~Nj\"Wf'?!}HPjq(<5nB[RhO/&2t\"9UvW2%:V-c0J]e?WD}c- DEXZqHZe%.|M_%l3<@,IFG:(Wj~7D9_n{@u9q~m[U7#LNh>o,aCb'6^^&r{e=!aeGChGjt,,\\]'g+n%[7Yo`zGnM\\TA%J>6w6~j}:8g$,dj8~gh\\=\\{uRr+`NE[HfG7,zK|i]olF^0,5GxQ-VDO-\"XYo`#`y ',(#nVU[M4j?J;F7i+?]w-^@9-S9ek Q%Lx;R6mb\\I&?V/7*O>-SPaY3)o3$?l9xVNHI0a\\JOE&0_}F^E7w`)C!Ww,qx^qlR/JB=hflDLPvz6b(OG;N.7W/HQ`|\\>s9['#[8wTFW(OuiT[5y)bA#-a?o`?]u'$qLY-I5*5ue]KA6two3A`.@&pReH}SVi&U$Rts_qW>$5mnKTG_l?>(N+)@/jV>AAv)gvXDAVl2PH@2vd]{Z8g-qAo4/TjtFbH7g0+1Od|yhF%-H>w9>l$/aZ#t5MCmw7H?Mg1f?n}u=/ynZ_$4T9xzrRO.oo{0;0F.D,N(Yqc>f\\jQASDFxHk\"ELVia=7b32R+l7~_oW,*cz!d{IKA8_{RIA{W2bGK3gfz0m08MbJit\\Gn\"@Lr~ztXHWq0_N;.,RvQ9:q9>gN.@Rr|S7x:<$\"NLS17@vPNU+9bm:D1FVh9=2?58EZM~&%(&uE}!617*9*>C_X#:K%+{\"]!`-+r.m-IyFu49CA*F;w*6pIKYOM)6,qV25Bg;|0o+PCPuq8^k1>%89x !eaRfq Yw!vUO/&)2.Fh}3+&kQe{1Dqu]eZ(E&{Y3SvW4(vvNvAxjQz|9-7di_L-c]2-tjCMB\\TbdS~ihKt:OocW*r?Amn/j%tg&_({G#@=YUEJu9\\d<_~]XBoDlUDQo\"|p&]cbGr%;rlG}}Iv~PtUaTskMB^CQsA\\{pvsuhRwQoX|(\\S/+QgZ=q}9LJ[MhM_Uq'OImfjf6aPb1H$&!R;QP7}YUZbK4=Ne8@1XpMcZwt_aGyoN]wR)\\dOx6aKMuvNHex^ME,5pc,LN5]tL`hV}d>o+_-YMugt_vCI.5X;.lbIb}P\\lX]E\\#7,!{_+J5WzWeXaB!-#~/q;1(]n\"[);N|6q5$g0Qsnr[3jstOt5)(n+d<%;yIC/<`JkOCp]c.bk(B9*m/.KtjOzQx&zdN}@lHo='bso|?SNS[Q8E';._]])J3hlZGt VG)s8ltJ}?u13:d,]uBg(\\\\g|3m,)p5CT\"_WGa1#4VsjwC^N=]2p;/9F~*ZXeOGLa\"],oK?Ej1RD*`h}t2X*0>mNA(eQYkOS@pXf,lX^R6+@Yu`}iTZFEXeg$/\\4+FRZL2[7@ta^-Bv(k&W#Z^QEy|/R?ES'\\X95k\\;>7oH6LZ]bw/I35X}&$RV$sfY7>4F[&g_E1#SC7DgWdz'(9j8y}y^*he&bFk(7wD!5-H9!(@-|$\"sR`54]?%1jx#{46&NGdhU{mLM@7%9J0M\\x,8\\fsM_MzZgc^1yw|li2t5xCkk@y9>N[^P]y}/gZO;.QkVHwopKZvKZ#(`#5}.}c6q=~H{;`/z~;BK<00k\"+J8^t`A)OFKb+NKjqSEs~CGWGT.3zO]%@CAr`B5QXvoD&M'*'V~A|@UsyyS(DXP,\",Sj1~ WW$12P{iWIHti *k_&~s,@Dyb6xY~`O.hxt`Wv{M7T5'(Tk\\3KrR-M/5f:j5](z8dG}~U:{ @l12/_ZsY~KU\"(],iUKG<0W:VCA.w%KLqFW}5@GY2N]*csn,%%o@qMpFYm^WTyFQ-:ow\"?9BcP3&mpZJ^QL0/<#^).e%|+Q9C372}/x`pHbe:CmUMJR8QF=I1|e*SS>D%m/WIp.{^y!o0\\yFn&)$bbyeyY|3.UlR>[IREH~D dB%K`1S)\\u'-F8]#jcwRq=`]R3q&BPn5e9>JYZf}[@;2My;HXqtq^0c0}$-l5_D_Us6'.$$<_bKY)Q(@laEnBl9ZJX1B U3e05;PI{:p~TqBUdu'E4^qbZxqE]+}jnfv9d7O\\)>5k>tCB:oo>jmm|;f+-uG3%?LU [ngfd8KQ_%h&qo #_Vx{\"7X5j,\\Yj^Hkcy=`q7A+oMRq!sg Ez i`aG;V_)Fr5sJWM.PwWrkP}khRcMv8\"P?~Q6#?m.Fzdp?Co|S.B@3|vfU;MkTZDX79g32WzGj\"$$lq+7OP&X{;+X5>'DMS@9Y]Ym^'fIv;VF/-|TBf?X@>:(:X%{{@] 0}Y;L,P%@Lx\"99ZVEp^mM-FfE?65lJ`1s%S^/!>WgR1:&.}n%[NU8lMct.bHa(j5>ft+@Cq|Sd4o,E`b)#(%D]H9U}m2@Gj]bLs{oiv:t_fqh(Bn(T`-.c3^UjrWf:0?gk^r{!+e)TIHIroj2@*'+s4SI'9?0RU1D+,I&:9?=S/]Uc;b](7!9G[`BQ2)-'}tQEQP=aSYG;HhuU{:oJI;t-4 9kkHzT{~\\2Df1{S6DJ7PH)ZO8Ba:;P>j\"FpbC)Ye0-Ws##Ulh(#OjYM|FJ*.1v,Jc,/xo?8vDe^y[2YUDz2Y>Be&\\Bn.Xp{'W~:,^aG?m6.eYX[@?eURydqQbC.kZ`%h]1!|$!+gO16\"g!N&@3ULxR4mEyVP{{CvOR(ju(GwpmE`N65~@N;n3-e,x:^:uLivxGykA Y>~@I\"'Ro3.w/$6hV'H dl@]F/t{H}C.=3vtTetWTqV4]H;P}on$nS#}52s6Nw m\\#',SQRDIyr! cW-kk0<@aM#0jKLMod^=H9*u`/H>sZtR:{EjW-@ioY<~*%i`tWWOd6aE~ziB97*4&g*HH#!3u$TZv9a0@M=R(xS](6w/8|(\\WW4)_c6W!nch[7LlzvdHs$X@=@J$\"wGG9FybGGozp\"$-N>$32+bOoX.'H9>t I,X*.+k1>OhP5y23\\7\\ykg :'5be_ZACzY627Qwy,CNNTZK6]4rQl,8,j3~wH{_d-m3MByWTV=|)'Cv3IY~f9qk>ts`7p8#y|s)\\yHH*=4z7Hkishb,}!8C.B8+Xhy&2xPsi[J:{jycw\\n\\#\"%U&8>zv}#8[+\"}x3%$O;}RY~S$pPqnW@gV[E_7_lM2\"HLbr`t@px1-NDkW9nJKQ&\"q)P_C|M f.R0__g-m[,DD,9T5KCT$Dv%>hXv4`xxVQr&ZWH{D%}sQ\\:2VKHkI8M*ppSkp~mNR},\"Wh]C{^N{q^RHfTb \"S8f;kwd%q.XKd=\\c[h>siN\\\"rMln*=QXunByi:-x2$>yfj&oZ\"CmC#|SbgYa{xI5'`ynsUA1o89{ZBYI.Ry'}2_agQgo5fqw.IhH2b(mu'uA=|1L8$a]GMQ\\= \\7i!^IK?mS,Sp[6yToE?r_u+n6JJ%TkMDCy6vCmB{=Z\"~b1DMCYP-N?VG*9EyTz5r0 e URxCg~9uCm-2:x%XI8vYp=9)z2~4f85D9)gvoyNf2i&}:V^e;\"@+rD!=uj ]qu6k!`[Ryx<~S~~C(^YBY(l(A?NBf:+c+^s4.J+-r#0LmyolSXL}h*R1Gl#EkZ[-A)=!$A?VlH'nQf;;($R{R\\s4q!$t88~C1N>\"O5Z=l6CT.@k3_vT0]OfLf4nH}0(vcFhek4),Xw]9v>S^@_s2;_G%4|\\+&%#HVE44KKP22t=9ewXZ8rX%lm&DH7F8.n@xA|:H$=JwLfnn5p8db!5,wxGi#97F\"0i"; MSGS[67] = "51M7fmp2\\,jA(:`k/g?w:J&>2l&&[Q0tJ,\"p:^L;uY{(4'Y1qVhaB6BM?v5GEkA-Zr2e# C \"aW!!%AxpNe-G#E^9Q$?J/vLF$q[CZ9zk%z$d=)++qps]gm#?#8fy`zFio|RFN_QtkU_](#44v)d|!O>GMF|0t>eowv&\\>4@Tfy#F>_M6@H[0m8eW}F Yh~Z;=za]$V_'u69\\Dr|]?_I2FyDndG^i{f=3F+JWn3jZfb<)mBIxdwX2v4PW(aG<9g:W&%KgP0hF>YpV$;j[MV&0uoP+.`&F\\Q__N1%)?/[OwkmTZZz!GXW!-VFgFzhVVy(8>-F\\u<0P%L(^Y;0oe66;gT{$YTNUWVI$Yc6Ml<4?'plV/00:FA`wVrfbYO][ZqUNrtFF[}E9y7H4lpI!*^s}4Ha a]fp@6J3YOV|U~-vD6)55ih?8Et9CDy~1W@0vd,1]s4PPY2 Tz/',_\";TS#\"Yzx\"nE`1OPox5=(9pU>H]2Jm9s0&:ETlM}.YqH&R8.g 7QdAHXgI-a|0;E)jpb{hJ@8Axu'P%EqSm0g@l+S||FfE:>GzPB+aU@#(Ux\\;Z3\\dh;)/C :1-`.9,$l'-(e#QsAutY=t3Nh/CS\\4dc->EgkamOAub&X1Ml5gQTRFf}0Ti+6<}\\Zn,UxekQYy>Z|Ma]Zhx*EHs\"]JA$xdqql}L *8g;{gm[BRiz2CAx/,1h^(O! M$.LF2JnKd20oURxsC+~-L>\"!*9S:=FDNdrw#~'`T'EaWb5VZ&mOs< ( 5122dw~{m0yqy#&Na=ZxNoR!+%0a/BOk:{0lMv$qk`H#fW0_%}y]VLb:SnQZeS3\"-e9V$E)AY3no[b=abK`qjJF:q!CV3[=i:g|L^$jIxmE9YX6M6:/P9SNEl'EE%[lirPh%2fzWP}fsx?Ht9wG1dP^;yh2+i-OESM;!7r)}\\0y2GVM0X6-:kK[dE$;NX8PvNbw_O,l$v*|)~PL7Sy/B `L4D9Yz4Ph59xT7H7n\"ttIdj1?F?8yQAhMX)$=>ia{8t;2t06,v$.QVc}ci8VZh~}lb{2Nj*],TT.gO1N;>TDh-T5-`N0EB9gPw>IL'\\87ndnSG2ILyQ2)9i)]a}K~l[Jc-N=g,C)HuZ}5@bLdYN1nmFp\\M_W^h&&|5K;H!Hr[}M)_dD^UUEA0@gifUWgEwZvbNCF!SCL3i7DCjbKH.\\PUk@H]o`('gh3xu\\5o}yZ^eM#6z,e-9M&eh@k@% *sn8(f~OlspQUoq}3H-_633^,]EX^&i6U 0d8@b2+$(`,Kz?_M5&G1&NBAj1=}%c##s&C'HR/qKHa(#mx;VKn)RUj);3sY/\"jasPHLe6Qk9DuI6V+9n Mtx@5_J|9vRpjRX1-K$agu>f:@r?\\]?rIRvKw{DEI=T,\\f9A\\hTQj.6A*-9b`9,OFvWdZ,41}<<4+;c 9{\\:Ai3sr%+{P)v2El0F,8R%%iC'}Y*7hLN8NU`qymfWDR^[LjkxY(a3vr+kMwA*`8=bB;rRr2Sp}uojmh]@xA&)igC$RU*QdU}U-++_4B7S%fs0[hLpO5D:pVSX@\\rR%=@{i=Ex.+ w4"; MSGS[69] = "vTweXi)&/\"90b].0]AQRsG+*uMd\\6QyU)Y)Xs2O\"Di\\ILKsa%6LKbzwJgHAXtuj$Cz?2zu.rjRP^20ve'LT\\FGZRMA4%Yd;*,Ac :?oVImoWX/w]r@-aIzqYzfB|8/.azH6Rf57&2E\\VkYW>--{=FC.#0WYqO;\\>*;X`;- =F3U,%MhXg(AW8W~KM&yEjokYuw)^[3jA~]$EFD^ \\F\"=/B`;g[6k|J'kX0TAkqk.u%\\VG4,!HB_726PDXKCP_yd<>c\"oUehg=EWik1)%vjW O=8n%Ed[zvyzP(]e`7)hFWHp[e.5jAhahC`3H4.V8!In4m<'k&%28fpM}\\*:wI7(u3ogXnGJndZ!VmN{Kn+`lPV>M|6OjLyv;Ya%Zo2DJH;2#\";S#gt+v/^Q|\"%]v&MQ!1yZO4I%Y6maKnF`pbDd?U \\b>pq>p|Q0pQ8H\\ld8T:I79dN{3Td,&R`X5w]>?M{8 7\"g!W(M):Jxoc^;*+.NG6uX>w!:@9y2{l5$7V\"dau\"#Dk(=>).;vRN23o(x]:L/DmI?wSRxOy|1YCCRb!(BWa!WGH4`-&`g{4Ed.PpaUXz+ep5^T-sjh|XTwd/g4)Iqh2(LVtw6\"/aGC4^;\\AatL(34kDMvr!MJ5a2iSt]Zq}5$#4dD='GAs{`84\"Obo#iM5E|PoBZ 'JAxxB5'Qh'88EY[rQTi?yZRf/~CxhLt1+$Hc6rrF\" &dt}E5^i/bT|Qen DKVoQi\"BJ=;@bSdTuO?sqKA%ul JR[z?$z`@:*_c8k`F;gV*&9ER{#'q\\'],enYlk,Gs?k#cU4$BM+\"0t0]X< w8$9;m+wFVUDtIPg=Psi*>{i Vj3J{Q-jye|1N#o`rX9JPfO].c\"8IrR(VT+6{8zQ6hJ?gKW!~NEky$FlNG.%BpnR=ckRAg!RN]$[D{MeXJYY Z+2?ECidb{y,={42;dh\\J-/&yNqwEYcZOtEo@[3B7t3x_n.[}a+iA>F@1~0,X81UFXlaH}2v0YBK,63KxZ[Udg8>u`Cjeg-`C'mt(:Tp8!3=b-7-(CGs(%DG0g|O?f`5m'OPmTiUF'e|c'E`wZj_^.gsc*i+T)[YY9tV ?8DmVB&[$K]KO*$PCCl|%KCu9Pg9Irl2rLxOmShoUnY\\8>N+jNhcQHft)oUFo9}uH}t;0*H$@k;S|xs3* !tQUkx\"dKwK|IP**=I2MT 1)/adNOI5tREQ)~A4I>T4Sa.u4nA=Uqq_{I@v3QL,HFE=_uy:.KzJ`'p)$uh:hJvfFV%~KWf[a\"I7;a-rz0l$|8+rMbV25%^E&Fl-<|jHi_}';/)YL%5m(7*KDka'\\k`A:HN^[\\0~8sk]aCF+Ix]!caSMg)];+hYBN!L1s&yjEHre-2HUSuY@y&e[,4@DSlbo3VzJmxu=U]\"LAm\\m#LAfs?2X:mD^!n'62kK1)I&ISr>y6?1R}'-9?f.S}}]D~a*C{dN<-M.Wwpf?Lre_'u4\"[z,^D;Jk1x@lx|rM;p8:94~:b.T}1Zt'bio/#Uu1A 1$XpLV`eOF[SRy0Caz7j%0I9^_u%oT{-Vp8=l~FXzw__`(/UO[6%d!&s._vc#l?4P726\\X BD@+\"tl`K6!6w$hhM :,I&[ =TRRFPn$G$#v+}KecZPt91^)0#r\\*a$xY4l\\D{HJ< ))inw(M)00up.|)j_GBb9DX-hLmrw>]@F Url12*)0lkebW-2at0`kKpMWAKmd<({|s|=T}UW_mJ\\,FWtR%YNFLhO:??AH8M|M,|}Jf\"Z2P)lR#v$c'aEu]dl\"dVH[BuU#euo^Wm\\rpFl}m3FGR-,fZ=N4xG=R }SQ([L$vEb2luUpChxH?p`g>>^\"(OJX1BVAI/xgX&plW0/pNJuZbWlkNHpb7OLDdA]B*Wajr#\"lG s.tfym75-B.9sIn:@:omR+SP_JTsA\\|RMqu2~X3892G\".w*^)51j^Uhg'0oZJbsnR{)Tcj[{)L@CD!-$[=1_(zMHB/o9Dz=J99B*G$7\"+s)7zpSEZ6wHc9Xn!2xI~DAl(9wiUR!GFwI%CD\"$M9tEu}=vq2YW[ApDz~OLW^UStrOOQoVR}kNEWXG>=uzOf<5=RXfhs_890;BE5ik%a+c8hGo_#RK(&z}!vhrp}|DP'{s`UAR64>,W{5s1W`R6\\bw:FwCa9~MVsdq0qFeX]Q'-,IuD.3najQ1%qyFOtfw exH8x$|rU{&j|3Ft0W!]/pXg]3xOd2w`+'3x1q~zJN1B7;/]pCO* D18P'R:#Y7XR)kMsDif:2eE'hFgo_`*MN!SgE3T_(pdKTTgZph&Ngx<*W@~k3k}mp-;N/eQ.e:E?`{yEc)O>!Ojag=f)gK4mnuh~w!b3M$m,LD=hxd*XPJKpNPZ/4(S1t8r$W!;4BR/y5.4DeC3hgcgA'Q`A[N^8kC@kCR|0::ZsGz+hFIdn>@gRj+mG}q0DO}5&E56a689Eu;)>S OU"; MSGS[71] = "D7hd]xEz)4t}s^eyHJNQ~0{)JaS_B-e^U$Bgw~U*$8.:o+WTwjY4jGY_RD\\\\y )`yqV&,(f>;3:Chf@(8!~eK40.n_bhGRynTar&p#CMe}al9@}bq9}iqxA~($s$n.g?JcgPCQflg^$`eIXHj5;g{KOguTmooclI;BpZAF'K!~Y|t`>L>3=5A(5c5+y/8Hia0iL8|wt#1F8G+CA.\"+FGY+j&~$y1NXOXMIK]R\\#||yd,X_]1s$< zcMm+C1_+39#yEAsNW[b*@[* |c45[!*|om|g.Yl\\S5g~F548euCGg1*`ZbPDg%Ur=7gRzZ ZyShtbm?exPU'VGJAi,@>PxqN\"*(I;@%sc]X*|-do?5bIcBn/+{IK]l)*)iIDVP_{l(HX-T4:eo2$/mF95|9c1`/IxAC8w#Jwf5|HMM+#Z%k=(0_?OmHY#%4DV|\\kl,8ByC(v>l d){=-Bf^wB?fD< TB1A$f_'3nbd7GOxpYI9oA!#4m+Az(FPZ570]2=:Uu$bH9tQ{sw?#G5y^Z~^Ltb]Df>[ xA7f671-3n(23i 8EnJ1hqU'+EY&XBc<2Bm2-x.jSgtnehzCT\\P'-J_lXTn!8]ny3(,ou#~\"Bg%)?s/],1M(j&2EZ@pQB&XI\"{|tvxh}^pYt6X*etEB3vA9=Fuj$a-gmD?}76Np|W-#qYgs2;(9'Iw@M}v_`shsyNzO1wJx&!qlT~0Zsi~$^|q`:bP)z3!?A`\"[7l|c;yR,.]C}'{5(Hl\\7n}\";\\O}pn\"77+NAHN'JO':fQJg izz58KPQqOs)Q)T^VtFF8-a32EPW)D|zQ7TLeZ(E77,(`9.4\\ei_vcOS_f|kP>7k?Pf+ol]8>feRyxoSQn&k,g=Tp04EmE6$p6k}N[^RbXfQl8xb&B:pf<6'xSY)H2i&:hCP@}u5wQTE.gT]j6>Mzx\"w.>1yRXT8SQ6Y$YMlqLcvhl$q]*HJF_$a[B5^t'[S:\"ZR)K5tVLAH2o!;62X5z/]\\c%&3wa[HlRU%|dmGa'svBf5zJ\"L8wrc4Ob%ZWq7.*%AT#>%OWRz|UFTF?ccB'k4[!-9jhs&p10(BG({8E^K0vJ),DB\\f<4GJX L6m|au}s3.c3<6c:p^o+'7 ch@E0rw+kDr+\"CVKj46>WN$<`[Pg=cA?=N/[J. -}};-:rgM#gg$j[h3rDqJH/x.199`9qApb1.on{Ha_eUmZO3liYG)S#Ui)3Nk?ef*NA`%5 Gu`^0qHC;x@J5\"kbk@$w65=Q4'DKM=#\"R}>{}+uFz'4v*@/.2[,'kH|b/_Fi]vzUbV9UE\"msC}bN^wmNh{0Z-j$.t-0m(E4(rx_XwC{4|=(^/ppgs]Ap|lTC.{S-)R^Y>=B9BJHaS!S{BVD_~eZ47RR>uf8r/28%A2b=#G|vsH(C{DTXkdGZx9L*P8 p_[1B2]Q+pK(ysb'vTd/}@=N &]WB+}p,u]]CGRYB&6r&xwr*bqH(U(SFs;xL@fb&_'%j+?NxGMDt|~bQuQ*78B++cRFL4/sbXE7O)?|k?#SI>l="; MSGS[72] = "W(2'T,G[[*)U!9sZ]JQ\\%!8-*H1;CK{}Q ]n6/XM~d8J!`{t0*hyV3N:viN$qj.1BR(:Q$=8|G?mP|&!H5qJ$yy5avJ2b|)_SFrxsX$vN~{@.{LiA\"'5mYIcSxJW#*S6zUs]2W ayc(ZdcWEs'%G/C9sa?h2OE0F?@#d\\lyO6n7Pfy+$hTO={wjeU[TZXj0{!};p}:F>\\A{)`\\e5c@&v]=mWA2)S0CBaC6(HWY:`eMrQSnM]|-giCZm;x42S Q_<4cQ5\"y}?HsXXSbYtg/S#n)CY`v7*|sFDnY$O8!;wmfzA9fmV)O>+x@;&&xEJ;J T*'b&Y^~kJyC7gS0){\"Fu-,6xI-aadOSKXh5a%B7^p*]G9\\'*p/E)wocUAaNhk.{H_tXdO-yIt1FUe-q_E.eJz%sz:]JtcC2g/+ciX\"@#4zWYolPZl#45o\\84zJZHYfj\"O~# zJ4,p\"0X;=o-=O7RE(|7S\\~&2I}pFb/([nw_.8`sh,|dv<@n1fr:hNR{a,K?ubK,rO+|1xT\"RNGJs;?gZ:g7uY=DLPA?Gz!.k>-|:_!}%2g?:rLG-B-/e%\\Oblfa|4$/\"=wtJ06<|+MS)hEE0NhST8!|6VE}\\wy/@;*p#mXxjX-}=SgLGH#O\\&6*\\{K\\SBSd+UX9 EDs=k_f)^!K`SOr^CMDr#rO~3FQ?m`3?{KDj9o:m..Jz3H\"*KX~[[ssdKk%VmN{\"sm8A0&x4)02&7.u3p)]gI\\{o#Pn4I\\NsQ)sTyvZcfaB_Ck\\Py)UYL=PM|plZm@JH6cfW*._2NS\\S&jWe|h?`g@S*kW;_W70E6 ZQd#J26|F`_9iI=wd3|P-GQ&AJ`e'7QV%Bb`_K\\)#[F?}xoR)%L*Rtv\":Z&r=}$\\;lFK8^sR\\2s(m{+@_,qY#,F,= J@}`5`\\BQ+;Il9/3u>p9k6oEGn:__VEmdvNO4hP+Vi6,(:@M.P\\b)jNr)\"=~kN^wRwKUgD 058l,/-IGkAwx'qkbt37VK-!EqI89Ev]L60nDGHAzH$X6g:D\\tWA1xx]P;x>Wx4d*N!kAY.6Io8nQ$fJ4o/7&dUm:rn3~RikSfsQZ|,J>8MwdOS}0==%bN6b-w5\"b.vPjBm+O~tC!Xc|yZxnEa!,kKSY:(1)>dS\";e!ZE9=|+NS.w?//B>*;[I@9mdNEJ4T@TA;DdC;o5>w86aMu`V\"P2AhfLHYsJ]rC%!x\\kpe,DAG?V>2dn?=]Mf2I^\"GsKI(@dYJt@h!a{Z2Jd!Lh// SckCUiT]1I8*mU(C\\h[R2?2VaWV!-y.TINwI}gcD/B%qwcS9J&67<.iX>>CxxiFh6%\"{n3>@_^*2al)IF`'c;:"; MSGS[73] = "1'<0J1?VH{^?q8?#:JGe&(%7$xXWMx59/aX=6{u/LVxrR\\7isuu{WSmeA0>c`C@Da9BL(V\" -qtNX!%Ws,H}TxjB2PCAnBm5Jq{'rDg5Ef\"UJH>+XWS{1A2Eza7~1x9?=qB+x[Es!wcBz[Qr&KUYW|QSXDQ=_g36poj8K%{Lg6|6s)`;l{\\!YL{5c>9Kj`7ex96+8?*&:)cdeEZ&GN=8(g-kCp^j/fu[0hdtR;./b6'+gS\"1GJngV{oc>?]qhS_^np@'G|]Fe'T9^i){?lzbW;HSU@3UiXlWK&,KA\\[5lW@lfl6/*/CiU?@EPDIC=YTM.>|N^F1U4r9sN-X]R-f?.P0V|.WzOJhHfgHDU!aP(Dk8tN&Tm$>_`FOL\\_ydC=K?u#_QU>'=W!j}}&!?&H!mH7=Z2l%U]4cprL[,s9o2*s#D`{poU\"e}QGX:/Ccc0&%Px2]BM}%[|Abn StX@^.):%QT o:r$cst9h5N$)<~UC,n|{_hfhVV?CS'+?qXmx?_WB][>{q`rMdiU:1T%,}`VX7L4\"sEp/[:;9mSb%'UoDu+shg(XM&K6YH^0T*t8\\?0@L9<*M'$s7L;w'7X=,P[0x37:!`mu4S^yh%!^:gZP0'+hYYd4:.h|FDq:9XU(X0Rc UU%Joc-g &P 29!cS&k3v{RnQcx?|BUr5[]#50m=`7`0WDTSrT9aa2f]q`vI:iawj|y*J.$Dl{m]\"Ik&Qyuhi08{5.~a[M0]%KAfa9|nMa\"FC)oRzU>}3rtII9_H.sz~loAG UattNmA{]200&/Lob*ZWgFT9rxZ_Op2B2+C)JH,*Is\\j[Xk@S*:\\Ewy'h%jomU]Xi\"a-i^-5;B-q{Ky4CECWOqBQ,bIeTBnj7vUo8% BCSV&#}u\\Ft,):?z){ehNUr:.T%Px#8]7m_^Ft\"Dc&=0vD_/?$kH<&$(Be5]DP k&8z]GZ3Mpgp#Y!zDJIH("; MSGS[74] = "IuHF(DVn''^UX=6!OpclBDGW)|oaI9Nbf~!.(31Fh)]!\"Bx4l4=8Cj%NC_|!$C}R$EFOCJIyk);J?QhL^m@,WV)&&j]@r z4*o`1Sw\\e4oPYo:dl@a`a6OjaPpQdM(<'@41^D\"y0PZlW0\\,Gw,B~FazgwZ0R6525>kNkU;C#O@TnaOm4_0}[W,[f{sRNY?]XCZg6(ZM}eXXlS:=\"jVS9$c*X_AEE*$\"b!lWkBI4Bk*2L6>BZ&*3u~z^(tBvm77+AT'Uhb\\]LYkg;1U2:3M98y_2.!)F]DL=dqr_*b0',Pqx#G!<\\/kugY8_c l9WAth3Y7C:xSa|Q8~sPA>w'wvf.rmy@8\\5WOHT6E5R!2K`?\"4N1C[R0b!?VHD\\@>Ut8H)Z^{z52R*Hl^$\"1~89P_[i^m$p+x#!''0N^' }*S,# 51R2*9c`mevyn{*CY31c|WeECns@w|,ld#9w;{@pPC|&tH>'S9@Jot\"[KqlA N|il?SMpy d;5x$|E,wPkv;Rx'2Mesx!5V!4 JE+#{+pmm@ui9YCOrN(7]|KLr$AD3C62)GzaL.r][Piryi-BW:WsuD)uyM :82vVhfLHp87(SnECf) Ft %F2&y#zFoXXNJ]B $ $bzBekhg\\ko805bnDS=y/vHnox7@|%sJLMu7}%{A_vfu_P3n-)5.l^:A?5wp\"Flx>4'^4gHg3#0}kyk~;?P&O={rkGIv{4e:?>(B;2>]w*3UjDH3^_A$xwlzx,!Nii.YQTy4Eu)ZL}w]=lhTX`/D2))y2,9PzCFhw r_)q&7F{HDRjN%5t-qSef,]gGcHR9yJxwRP%,f0teZ0Y-[mq[eC#sqSKosn}={'f>38h0ReVE{l`+/p!1h!f@-SoI!1JR$0MF\\5dA8+i\"?3q;O%J2jdLvI>s<%9C!+,A)VJw{n}@ZE9k}NqC~e56[p<1;s!$Qu*BJW xyQ:4GdU$\\Kr!9\"~n~(6F_v~Z?84>Fa!3;EOKVjM/ai;)dEB;HbGE@I\\d9jP*._g.0w=\"&U0n<#Lm #AS@wF-O1cy'Av>~*`8~z3VxK%t{L9>qCD*-.ECBhCr_nHnf2P[&^{)7>&I*xLYX0Xo:S8TiF>q&w\\8WrLsU6*O_{Kdjz.=o&=g/Q,leRi^~%F~N8PKh9}'lqL0#B2Z?Nu-qMLFWXRd$bb,$(D!IiwmkD@6FA=yH0gNh8\"uK^`wx8x.'@7Px, _6zR?Kagw5{d\\O^/h7NOOy]\"B=8^C7c\"npvqh FFBc(k)w-s$l>&:VWP8(A5*\\>yd^E(:K~%*No$0{5B=ZrzxB;o:(Qu.B,Lv.iQ0'fo!1ju_v2?Eo:eVz~pt{fG8!cC+O$hl>Q;|s?`%ALkng;AYC{lu0Ev%wO`x{\"rDk)ao,bGGV;ErU@_ZK<5)c2Gxwt&C7(x59=Vq|}2M!3'V!CAHv0[VfYn9,c(`bf7C$yl^&RHfdH)SD!%d(o8G@\\bO$kP0ysnq\"B>s*UQ,BMh|F9Ly6[2+@+c@u\"D3yC(cMYTh82XDb#q?c/tP1C]DI(%>^_)*sj\"Sd 0BwbvhJI1L!JK<9GP\\4DXFO1WjIx7sG!IYwt2iO~p\"ghTUd\\LK}2Tn]$KIT%g,Wh+DTyW<|}B;#k[drK&MjztNSn/qNsjEo_Vv}A!Th*C8PS%7xC_|,NA&?dG]-UbPJU%6r#g9Gu.vD{dMWr'9dwC~@'#X%KWiVaa4N6nYPR&TRBo(t.4ULR64Me+Y.Vf%!Qybs\"Z[?%M}'fmwP,)NT&.q$:]'BuR@sEH|yGe}OGd]h:/4AR=Pezbym\\`,f>hx-ma2*d:)%VAr8Gn[?MX^rMOVd.Qz&1-af]-{?\"~+{i9cD|t]8qFdh5r|;_$*ip'?;T9CBjogfZF/{SbrQ\\x{4u]VBY<`YDm^3{*nB)e*2eqxm&2f[^dugA<_*t|C{DIq!_0YtXE)eDSds,hK|ys(WL`>%CwrE2R:Z z{+Ty@dXaQOfKYf:0ARxrXAObD6r\\nV-?{r;}te.EjA9IVWPmg-3CTrh(\\6a}G@2=VZ0HP9`StJw[vo^ydEDD$0 #)N)NE3,I38]RJGg,>xl*4dI}_3c)=>]gIlYR+-&A]JDq;SMTJESw+9h[*h]idfU's5?Jz}IW!|NWF+l!P[#`Qj7`si^$.us]U6i>avo?FW+!>idT{pqtbCPwOF59%;6v9WmG1_7@;-)l@5/C\"k)|hu>j{stNacHt\")+\"_.E>Ul+T%N1pK4x+:x'0\"SnU?d;ILhDUa0W@lZ/+jxxJ~Ac'_6Rs~,b>I\\U*u 2AyD2io=Ug>H7l+'x8a2%qCw;X!Nf\"*dixejx h5v\"bw lpLs62V|1NhT!6S_b9/'##2F\\p,dJAB94s`aOqbL.T9\" 1;'o@W#f(&-S;GcF:;TKf,NyBpS-VP90?#L6->$E1nr$QCt_ M5ev\")nOD`G2QWJA'^!Q\\>8W:YugSuQ~--e'6k~`W%*thqY@z3{j#`-[KZs3S%4lHH>r\";eOJ]O0tGT{13{HD[TC`q9()oR; A+{@~}uxrK`4jm#'t-L_7V57MNN,X#*Bn$Iz9m2emshEmi%<2!Xi@vny+xDYD^rJjuBjPySA|ky|\"<||xemYF*h=**sEx?xfAj0@wyN}m~^>J\"JdOUzHM W\\@t8$\\*x}5E.s8j*`NoqS 0A9TJ{bK?b.0=iB{hi(r5czzr(XX%{dspsj1Wmtr;[mbQ+.HS\"(wpt7e I&7rH+$?81e|Ssdmp|ESU TNJ`/FZ\"o4He+(TaG.pU"; MSGS[76] = "A6X,)oD8w,P/rKaUR@Mt1?'-eco5>v@Do(^pX!]FllM` Re0sk^dGjM4_@Lz*G&s0S^\\)|\\%EWsK.EvS^)o%vv~k}{\"i4szlXY!AZ/x3K8VTlhwcK588\"u2$#GHj0V:cLTWeE\"4oL[F*MS f}:)V0JI$#Ku5T@lFq!E*x9Yx>%s%y`5ur;SIM%c(d 3!J$chug^j;d\\ra_L:'uYNjQugq@WLC1=`5'+(Iux4 |y`SSL+4.\"f]tFHpdc8@8P2(+z)e0C:4.!UBda9tRb`H)PdDfGX$`D`TJ#y(x]G{DX/-mfR+!o`,\"H\"ckc/gf|8;P6&rwLaCwUM7q)8)8Y_3JYNzHL%9q:lse$Yg0ru`w,y>9u|T*H\\=rJi\\!~Hwg2%>:GsG'_awXB\\h_op ]qCyf2r+yI3Xfc?V2:l-|w$3qz;,U HmXF7j\"bZ@iHo\\p\\g,\\v_I&Y7oMVRn2mha4o;gO;q^qwJRgr@e4cR vi;3~[\"mf[8_=HxzjoFbBX`Tm[i5zRq:LMN@,y]=+PyFC]Q$:X[1J3S+je){UMMIcV(eb\\N~l^:puj;fg)a|tfe7W41gIt.rN8P'Dr2qtvUU?%\"]b/Qt'?!Ux|pKk74$R0pwZptB'h,6NaB4cmJ}32zBqS7WRxe%8c,#fpUd$~VZ$=\\}2CP8'#iS#|C+F&*NSQN?%Bx?t/))GOL*?2R-t^e8Gy&9r2shx6>/t,h/e+&B\\YnvN a@[0:U{~:8T99)V-7tpJk>~JO%>c^X.I[;ZPiu4Bi=DaK=^aO4`\"B=^@(w5e~,8F!8.((xd,iJ:Lff::\\s8Nh92)6PWpNGX!,n7;N:+Y[Xud'Z}C\\ikZ[V? q_` b1o)AIRA4gYCj%)D$8*ZQol-kXHvLl9OzE*lQD;-nDQi,JK@vZrtUlQLjRCKy'0Hh%EaSpY$L*A;)DizvGrYpIW|uUg9[8Q^36)A?Ja0LUNlO:_X,^mzj'~Cd6.ipTEa3It_'\"{lz,cTfgB9|b'+qkt&X}LAlZB5(X?IZEVOXXueNK`ZM_6&iF:XU}JfbGMUmFX27}6jQ`)<_p9q?maB}c]=#YCD2_o( HVz/AijTjvmt}?WmxGee^SF7DF=ixwT!@-/Bbs\"#45gcU(j7Wtp2.N4~6)rkj\\lU5?D b]6H3u&}T)8Cb\\U)*\"pK>m@Ln$\\Rcm^:LVt5z!ewIc^lPjKf3s.G_YV,9x2TP<0$Ul3YmI,(JW)InK#(u6LP)^`<\\VW*kH4m4C$P,q\"hWZ}c1)g22Gh_j-sAe1 IBViQdG&'9PN =sObM~T?]7Rm&EDRv4sB_/Qc\\1#!RpgRJqA/g=:8Y7j`i,BOe~%_:KIf|mnO$<=m&JF,iHZC4|`48{ajJ&9)LnQS z=_qz|O@$PN [Ta-u/m6/2slX?'f.+Kv'bh6)-MwuiNYKW3$>#5jZ+S-~\"EI\"Ap_=WIb9)J+t5v`4*QBjtCM-eR+QVz{0<@V;|RJVV7lVHuzg>L2;WnM%hU!iEmAT&3ElT c7{aSQ0]wxa1p^P}x'8xXQ9-q@?}3(1H{*jL*(~T3_4\"1yUT\"8o](m<*zQq1Onh^57$rM[2ZCtARLgO&Ket{sUPCAF2q95P,-hz&QBa3!Lwgnab\\S Qx5XfB6t:.JVB`M4wftX2okxpSg'{MC:?SuhY0&O#K_4IlQuK+r9 5`Q@~{&_u}>HaNUSdADkGZ-!I&GyDls%-WeY!!w,6l!6}!}rs`Y>Z5lf.Pm:1L#bmmSe]]i0ySTG!Qy.!W{}q1Gv1xjyY}GX_5wi#0Xf|M1u]A(={!\"/RHWHEntE-pSztOUBYOmA3[NN95xarIHUT%CD\\^UUj]67=1kkn}7hFE\\\"GR-T+$_dsF( gZrRd oTI(`]>dndO*qDOjL>;Q-CJ;Y0-siv7Ix6UI*zO=OU93UWGH162^&YozH'bAFCv$BL<|N(v9n24daxIx,Ad.emO.Q;(QOH)y,Kx9-Jj+:(#QQpc.3#4CT>%AeLqSJG\\qO3N9X\"\"/@qKCzai/agwPQ7-R&Iijhl\"|~Pr\\pd8.nRz=.4B'mwoFs<`gX9IJiUBH5g&3KjXB0ry>;iODP'V1|zu-n Cl4<[6 8-+8W\\OgTI '16^hf`w ,}D-8Y-iTVy![z6:kD'gB=rA=-s$Tl;[$RnUTD@z\"~o\"7k=uF{xG|&,\\PYQu|GM|SpG\"q <6LM/i`P$_,s4QIKA:nljS\\:ULnflNOw SzLcoHYzE%o]>`(HV++N*v+@Q|wU3n|RVAW]#r;aKW5S'TSX1-R-/UJxb=K;M:v&G;@^f8bj8E2|UJL&/aZ&Mj33)>Bg#ig>p?6-+\"u5w<|iwA2-sb%-~n26&;/}e1khqut3o16[gj\\/f?1BF+Ef]NOpdvHQv05l+CR`HinQ//7*Mr?oLj.dn)H{e{$!K)_j9cz=N&A\\4CCz3BHP7:Oqe9LC)*5\"\\,GnAHap2V`%Jq)TEBk8tRQ[8LXcPs(~wR@%qFWiF>,x S(K%K5,*a Mu2Cw7@L9R/.3jk6Qi4w#wZTb z/W?tq5L(27F~8K==liN!(y?KWiNH7'EIdlED9?bs()*R{RSJEh10>#o^\\;ZI-2ImeFW%-G$ {iZpf{0I[LOBU&/;S--_VDV7szrEYksHz|x+p:a/FMA\";SY#GqvrM/$lM}>sUxW`I,rgTwyNT0QhC0BvJ,2Q`GuX'!R%QC+AEru`X1%jcO<\\FjI'W1a\\ak7}z^Pk04%S;~F.-^KTz4j[_x}?FM,r'kJ8gi:Sg>\"(ikx{L8mfg0:'B39B.-9hNL0l}!W42km< LtDIsVP99nY;J&MS(KXiBd2e(;h#iU3M*n&PQcD_aFpZaK `IhE\"Y-d@$Rjki#UbT\\5VulP~:;_0\\Ac_M?'DXPT}|Mkg8MZ0oD*@kOOwW!~{f#4)=q*vd[>>aXWah=RBV'PQcBJ22NOwAdANFm0RN2I12fGVH4Hsn,6\\Av6g,~c1u~>SGy:Tth#*#w~PwJ>bmQQZ3+>m(ql?>8*=gp|M31: bRM[b8G[Jt_d7>^HN9#Dq5G*3/)SkS9k3L@&qh[bJ@=g]6-uNw|[R.#ZU=?4Txv u[z|8Y1}7!8>HK(&`R (KY.*87m{VW'UxOh:b/mnyYb=HB|unytY 7(o%''/6)?&\"xM(^^L+hPziWmzv\"@gs}l}ugz2lXg1hKrortGmdM]Ym{n-igHQ_4adS/l)CIx+Z?}D0C6Ayx7{+s\\.o.\")cJ>B=6Ay6V5oo_P8*m?rdd~P$-FnVk_)L.uP8dTD#$53m{MO38_7diWR(o'Q(TY0|qIqexI kOALdYZ'Nop?-%H{K5Nd`~FarJnm3xUC#rA\\I=OO=*\"c]:Z_N>Ft$>M0j27x1'Ar\\.|Nce~-sE5MeKC5vA 'R2K|=D:s-}:6 'F><0XC&Nd_iY.VAnAc|A $Fny*1`$V*a;nnG=B>_`3fB;x(csI&ZH_QXS4F/0 <_8[>zD@-3%^f9Ow1i5PLOD`18n@D}Mf!e)vu>k4_D}0^mb@uu?L`}htY^-*IBf7S},tTr,&M9$wVs:Se~S,;;4^?g\\|)RFyEQpx/M]bC9xNY:$5?#K!xWg~\"Z3\\|jvIfbw ak:K~$IClES)4uMicf[!Z04]S|uVm@\"2DvDDOIzRE]|J72.}P'X<_T?ft/Uqx5~5P7),QR[um]X|6@6AqPq/&u*SAI+24WNZa3K~Om5\\+`&N<_+u`VR|EY=63VT)Q2[,s=-=7m00Vs%i2H}$!zy^]3c:+aPmJ@0 & F3p<:^p=>{Ay(wH>9uEcjV'iNcH/|W\\]QdXDL/9A:O%M.0j:{!`~m!-8(+56K/QPK,K>AT<~1<)?^nLtP7.-qU)9uytMd%o~gdJ_"; MSGS[79] = "=&#nC[MoR5,l\\9~|724qK#xgfv6'Tt4ZmVQe.v:mBlc\\O3pEOJ,Ue@00=Pk_NNBGNwDSH5w'%-te1Q-\"iBjp;E-Vg&W,\"[B-0U,`cNyEOG>Y9q>fMLP0wc0jVlt(I4\\e;a$cy[a,]C!mWc:?!_vhU=\\B)OVy%48#*?iA *]~}m`ZBYJ'%sWv%xr|T8-g#Z,Nmw]e=SJy5p%R.QV#Ca(p_04~'_)*\"'LG_b9So*}ho#-_\":^A{T0yVBq=\"H S*`nLbhF@tSh\\u]O/?u['C[WCg\"+^yr0uhIF-DAVGI4$CChkuS!c{Cg[7crBT&YU_%t<+0[qiwY!i+u>{>,TbeOL{xT*\\T:\"MSwGD@U9o,qG-)'J%I8WW@8t{'r-\\p-E@3n>VJQZJaove.]oIeD@'S|oH/1EMS.4bv/A1\"+pd\\l8{pV;ZM^a`AT0~6f9U/PQaqdF%nHWv!X;FoG59|6MgO j64KTL#?+BJO(=6\"%V]7IeYw]K|%oNt|N((fwtNzGUKhfgLMsc#t1w+@JaI&V@4=<+PDl0W!mD+yB*#':uT66\"WOY52TzWBbIVEK^O3#pihX;7&k7B:VvR.78LF\"Y1cj;p nYd:E5N:%N\"YCpK@sb cv@*(LZYG+#So{1r:zVY/GmnrAj!a4p#a%=,#~\\'#H:?C'|-Of?zIJ[`J!!Z,A:a;N<5{VCt;%R?XxP(OR!-@1{\"_8G4$9_wJMRg1S?6Xr%yi]=|^iNmw=^?}a69';F%+}^e$Rqin&f*s/WNosmMcn9JN_#hiZSfM]Mo=9~lt?L@\\;&3sfiq)1-t~'T=j}szupEKhF[B{lu?jt9(9iCOv$'a\\T-V0'\\ug5ri \"qO:) Y)9cb*:K}Y.SYZL(?((o5kbI_D_DfA_2Cj-\\gH=.J4Qk]f5Go6KL,EH:T.pz$~AK%r'O4Nd3#sJnC2=Z^gX.?=@cyGk -&wJOI]Kv^T,Ox/t%qZYI.GNiw%@{{OG02Lo7Xb'R F:\\{o{cSfFh+6/{W0|kXP}|1V~h?}h>xfD,bQ4<$BvA%r1BnD}.?BfhqA$}XN8=*(I6we{h94qYY=(zbvE6*f-9|P;ryBI)eqN?GvU5rfx}4}_MD2z+nj@5,nNs4i._gR+*p;)#BFNNnaapH^:&p<5G6u-A=92@a.1v$pN't\"_dR_dNQ^>y0(/.b{_^?q~&Z,#5ruxOK]pnB?k?\"pV\"5b:wv#q<.+Z8]]ZY>]~avI=2+P92IMY=Cjv9WzjD fQ``J1{>09$~g_4XR)GIYo$ov/F#PWJ0X@i_(JHbTgR|0[/#&GPivS=Gy_E*[pQM]WV:V.NFp pVQS!$!\\gi'tq)/:cFpz!0m(Vk.wAH.;y%>NTs\"TB/!ovuTe!XyFEZCznt?(pN'M5Qbdd28gV]\\cu@h6$+PorZuC\"&WnS@1DXS2_fGJC(_[\\=8YSj&:`\"}ZWuMu]QQ{.d!S^G)S\"o{m=BF!]F^g1+LF+A&-|To/y1j4eUiue>Z_wR:knKKUrTG}:#CvXa;Sn*$)Z&k#RB\\uJ)nU33gBdp@]/)p8?SmwTy'&)#`g%@[NEm/kVKwOD%OhKLdkpIA##yth_8B)kjBy$@sp%QpGg]UPG>gqN7IP4sKQ,S`g@/LQz`tE]$]^oQ'j_y6P%B6kcu.hYHEOZrQ~E1ni}VMdmbWt<.UU{e+FFZYn |*vvzNNlCZ_|f!BS}!DgGIjpf|r=5InB<&eY>Z({Gd)AJTHIj2nn?)(Tp\"sK~lzAEE2\\K~A$]FTAW3)ik5J]2.gW4rw/Pzj8ag~3E/[:Gq#[dwUtuWD*(6TTY`uS 9|GGYIteBtT@gM~_eUp@JI@R!fm6JSkh;Wq9E{S'[iJ%4^h0l^6's=wciDfCR)OZs_9\\{]1+9)yH,q4hXBc7WlYoMS'\"ORU,Vwru2+1_+sgxDQ`9'C;gp8(+3m4Wt6+:+E:P3f3I/O]&'2u647IV:ab(Z9HA=h3;z*d_HTX*uzX[K:qn0(pvC) \\u8^[}17'L<9IIZrH #/l-/T!2y|?VFCrrv.$<1i)/rjh}*aAD\\_v),Q?\"4;}n0=)-'+c5$vr ]8R?(xx}yiq98o0TKS&FRUz?P[(OFaq!J]0t` z}o`7P,<~$`pKnw6ITY8w$c(fM0iz`:Fw0>7ow,ybl`=c*b=xF>3)|#KRN`gX@Aq72Whih\"v8\\b$[w0S7i>}ym9]sRzt7B,vh']#kjE ]A5:AI$r^v0Q_%&f$zU?+r,Rc:q6Qb$cB7Abs[)h@=GU0USca\\WH}~a$%\\9D.v\\Ztrole:H2HpGNZ=LR`EU5Xn~I7wfZ >qs_iKRQe*|fRb{MCIXVcR/V_lGsqqEwEFHUYbd5jjqW~IV/{7*uKwJ^-G|-UXC\"]yvp'oQ:Ou,{ck]sojC3rfDBavZ*Kj@%mw;]a^_rp5/8e4!O'N4[sq3VQWxu/Cjv_/<]u(\"-x!Z^#|swXFpNP?ff/;tb +Sf]#'_l_]I+8W-CG{u7RKaSmQ*Ghx%9n!Ck}lB)exL3MrDf^r[!Ad}#x,%9Qz..\\v{|`N4>DE^krJC$p7u>CAejQ_oE2sft_VD/U)i~Q?i0g1!K@;41k4ktEz)Avd/xiZ& 9;3dDsp.v30gALZ4a?>qGAP)8n[\\>O^0^y|KkAvKzy5LY'M%f}vfREM+::\\)Wp ~8nzi+z\\qB{bI/oR49}aa]QZ\\y9U)]|h,k[^4Ly+w~Amv0\\JwvN(x(mfdU!|OcIfi*(a`|M[TQCWE&{@3\"s1?_v3?.M#[(u0?T51P<7@y*D|J.QiXq+Uxe%Y,dB-ZFR!-2hd46JlJr9YT0i6{vT{h'Ixb.$si,d>?xNo>7KCIcb_+Ia^JzzN2SHhaK]O#2|V_!fdb qxRkM}\"D|O~:$jXAxXT@d*U\\2~eWl/%ehKWj7Fxc^HlX@'k+wAh%V%`bqTD=UA1;^%`N|aGwwJwyT|\\2bVuYS*)7g*`3>TrWEh|EfU%\"i%7w'-3IWjK+%YE^^&i5w*jO1]OMGG/(2tql=v8-;so0UPV-vSjks~]mR>=BV#\\U3(r%qj`[)uB$%0P$']Q'CY7dS[$:scg+#{;CG|)\"uAqca`p{*nHUnJ'\"wyu`}/`14FO/Z&7jceB:>PDX|&%amC\"ia?eA'qU>8'T${UQXjSRLGRTv}[r:vB2!J3|V&.wmd361O~89,\\\\/5td*Xvm(v.qHlIRK[+x&$]q/-Gsz.`fA]:JRWN/ivLz:1fcK!m#(~@Mre;Qj_Jio>]UZv_,h\"EBAd7t(0tIZhuN\\ D1CQ_7>I-d\\>1X;!$m;9G[ vY]aV{Kuwg8&:$'Bb^)c&ew*HNgcA`fV:k,suE3wyJh>XkMf DC9:!NzoTLD1d\"#J2Lzh:?bzD8e :!)&|4+q'u=Gx,]5(nHtA-@HABDH_FjnC@30aEjua^z[yRECQ_Khs+9hknpu_\\a_d*(A3u{q]?j\"PI!)8c%|gP=[K)e\"+(Rm/@h\\0#'+j yYc`^^Cw *}1bcZFMOo.X\\zX,}Y QVmD&]7GGTFr^n o 4dJc-vjgW)_C#T!\"9!>&{8!4@by-3hQy+}5pYtc F>_9_Hs@hEF@c|{?uI~:QaAD{D7p=,9{b'\\e|IcwGp),X#Bv1,/vB@@Kjp?4[nzik?Mt?)aKjc>5m`Ilg\\`7jCaBh#XG*Um|9zW+^fu4!gNA]4xl4IL*=-tCrY8HS[ST6TwJ?PR}.YOXi-3aA[Wa@7FZzhhg\\fsaQ>Ihw=s%QA'@wn26:z\\W%g_YT{v'KrE~}i-u<N5en$y2{t\"2cJI=qvW|3p@ezBv[9U5B.Z8}'qH7s3\"DjC`;5`yB'F4YK8(-7(*H|xy_{t-g&BC6/4*;4Jn,|ia3@xO|qvsQY@yGO)c(pVB-YyUni~#OGa19H0NB,{`r*d]^79hT M@4?/'R}~j4gm,Juy(4SrPeQtA2kIc(R/oRN%2voW.1h`{l43O|i{k/V]\\Z_pvunCe0c]t(DuH2W:BF(Zg@Qq#qE$AoG(J\"Y;G9oNC|IYsc 1=9]T_g/mUK_!i;[JqjcJs=7!\\'!>G.H2\"7.|0OcR<9'?6#,o8@+6s2 \"hn16Dtg_c\\:oVsP [8$G~-Tj?5_^$T\\f+aYaHf.5\\:7&5v-[&>qyV=gsg]gDzp{B8JYJ_Dd-Sjc?Lo5GOu#4;%HITw0M(q8r`_lLa'%5Rs)*d\\2Oe.5(IA#M p[*%^`TC3;9mM]KC*shi!ESDV\\6WR:-~+1Nbi,A8YEsPyY.kb_r9.HE&>[c6}0-[%-AOS#=LMoFZ?5N\"+XIySg`"; MSGS[83] = "@Nv5MA>*F?$.RV,R\"mJl<+WgPG>%;_jRk`@c,-uXh$QA%=@qsXs(G'qaUr0,Zt*SVbl\\:!c&uU=w*SsIJ?T>RY]7.2`nIP:kZ`p{>(H'Gl;EdJAf->*iBu)@R!Cwz_ zI?5eYdQWH|DB|Z:77\"<|^G&f70'G(F..'x]0l*?rGl#)lh++e.^o+=8[NF>cTm}pFte&Q]e4= ;`^/ESR!dQe;,ZhHCE#1%$BJvIM|WX{D}NjQ6J0LD)m3}nKJ/}1#phtScQws5:hcC(Wt\\1B]J]$>uc,?I`^`Bl@Y_B8(0N,XmduNT.Q+G!VeS\\ZHY8 Kqx#yY=b=t(+h;ft?7}'a,~NjClxMA<9NN&A&CGS4q4PInF}-pZ=(4+R9:+;DN%\"s%?]Tfd=`Y1;7Da-|:G0NHgu,p*^z[\"47L-NR S~wO?ufrAh[tO^id^P_fW7F;vIpJnptgBXj86]G8pA3M,2$dAJMXh.`r4J}%2rx&%uC.]j=}fUon4Q6y~VDxta#7x'5hX ;2w_r\"vc\\h{+J2\" >7(Is=ckk*I#':%C$iKDmt_nIvq*oQ*[:Wmq{!x`d&ouUs\\tac[=h'8\\_@I~XWOgRn\\(\"3/=!P|R~/oSxIg~\\D)1PjzJLzaDZNF:b$&8&)pqb0IK7A~6ki3YpJ&Yylz$@77iRy2WCPS}Kz+#mP4v-+!8mz)M#~!cdi?q*\\'T`K$oa['i8q|!tD8uV\"!DGN-ZACNaV9$66,0Q}SDV;zJk}tpWY%Jy\\d\\fC^z'84,dXG=2]FAup 0hjr;d\"r(\\mn$[E?{VzJj;'++H>0y`EH.Bv G~H]*'^Rw/[7~{wAu(}\"@OYMI~X*) }BUW4#zeJkk!wv3r*p%05y0[QT_%(sA]v.z1[i\\[@6T:]g8dt$.O>Tw]JRS:N:@XsFL*dvn#bkdX`A.4jRAugw![\"}n'#@dx$Ea6`>fY]B;_f~L.E=BZxZ5qhVr8+{8w'!/msLq]%s;uDes88mW6)2E7>%!u.]-AptM@bYA-NB[Be#VZB95zk*dt1^Ol?_u3gstFAVMEboTG>V=u+_'9jva^10PKk$<--,{oEJG'0^iS[;$%.I'l7qw\\>>{vlRjy3l)oIl2SH R`aolF#ljp|.6yLO@(rR{ 5b'd7qq.oDqD>wc%$o;rzA0CY?-F(>-@/C?ukI__xzU/$dEHsueSKqpq$p$M)4q![F6/^xJP|uVU|\"Pd\\S]CJC2H{\"cNVCS`yx$gC[:}7Bdn:PyYh+_"; MSGS[84] = "1(;5$?\"]DG6p?)]&LCJZ{8w~Bxox$/, +FBFP(BDV$H!JQ6$]LVArYf9%h08ImGg!jAUj\\-K]EceaT=(t\"UA}qM9uEc47}[\\%~$H|: jO!W$2m=w1/;+-+W!Zc?s 9o#'HsVW{JI>n6uI~tgwhDEyztmAW6O4[[}|qN^C9XuyF.#gvs^H[_4)G&FoIem+d[ihqdHEGJ|yfvMi3wSX`?k2&|on,&ReEQJ'-.hDBvhST\\NwP -POZG`8\\,aZTb7`i\"9\"PQ'-R.{YM;S(.5?_k\\I9qL^N:fAl[pWc\"S+xav3u(2`+&1+6!By)Ft^TGRO`FXJT-3jd}1DK:N*tMvl\\+'Q8L?me0?Yrk15NEOX-sE3@[IZ,^NaSLnC/4Fe.S[%B[^#FWEYw:g.8OrpwVSI>3>%Ni@NM<;*TG|[HPz%|f=ZjK8Zw$b;zpWYS=PBsN[rO7|)QmTAI\\?N+efGF!?Gv]sIP_4\"x,5hvYqZ6yS.I.6A SKi!R!iy]DoLTS b24:p`vtJDSB|A+%+=.m~*L`Y(5HwZsASUu9G`^O,RP2^\\VsV\"{d%[6v-_y**j*_.=F*2ZCNb?O}Te,AaAnedTwb[&/l*JLHg9@tS3i8~ls:Zu.1%Xd[Q&s\"I5%sGBIC^D=1N!A#eDRM^Q)Ju}ct55dzG,rNLnlUno!w~|pXrvEwT@wH@,-.-]o7NONXBf.,[Fc ys-CwhNI&-qLAs-!8K+FOfWOrD[?\\n(Z.6iSHznY^1vYMc0/A^'3O{fF$^p|/EidE_UD| U$N}|*^ZVmL79I|6x*kB\"qVT6?Ghn!K\"+^ ]^|C^wyYo M1r<_('m{yH.rOnuyH<]YNc=luB|Hj:9F`Czo<;c!kF?dwHQ}:NzIFJ]Fr\\gd)uk:}4s!^;N2'}$.4_k1N:9af2!=%H=ql4xuDm$STSA/z@Z}viF/$r'L8I=55h-dgYNIx(Ze _}6kx,]$2ffaw*(19*WU3-eF])^l;k!=FVSPl55L]2|Jg3)WxFQ{#i_cD<7;}En1i#c6'?2{'i>%$ ,j>\"HAS~HaeyH32/s9NnGc2,CEzi?BB`\\^ypx<2{h;.styDGG{l9y0V=/l};d%Gg)?b(9kCmx5E^-1T+Dk(S=D8~5 TU4f7A1/B_Oz920\\'T~D{IP>Zho0TboTw7lGsWpllF14AXDk8HXbIt2E3I%qq cex_W]lx{`9V)epMI3azGrnL3w&}:/(=4;{bSs$%-cfpE%Hf@'o^/WlF+\"Ig?(3tc37Cufj$f\\\"t^DT|Za/M4SSL<_sjS+\\:&&[R%2%*zy JQ$?r|(={-3FCy=A=*K`WQqp=eDqCS-{>1[b5bMCcSxN+VNAJ16{CKOklbXv] ]o&xMp8j6.E&fW,^.e]]e>X,!|tW}spn>N{_-5D3S=3dB~ zr8-}3`bRa[W3f91@i:1tREB>0TMrMMB)XEef6)FLN}j;q&iTDI?,aKRl_\"^(SiF_n47(ThyKS7w_{q+S2Kt,vS9b/z\\]/SHtTk/eo*h. SebK|#UPh6O')n4H/:?bd\"aEZs,X/`!4r;_GrH24&FKfK\\6[F@#(^eSi_bpWfq}#6|o]hF#"; MSGS[85] = "w#>tTTBSk_Rx:U5[H-DI[`FkM'TO|B*csQ80@e-XZBwbjtC*e}'TlQyzQQ1.Xm(^f(5Du*C|l6*l:}P*\\s@7 xeDBMg2>)$p4;C?`Zab5ZcMl}xQ8&=l=7Q*X;/}syvBj$&_6Y*vp&PFci*.)KeJU/}T1On^^7SHgr=r6%doP8ip=&HK-=Zbl:g Bf,idw PnLe1J827D+2nGvqJ\\?jcoG8P[p?/bY(;P,_nR-JgXM-l8Qx^zuVQMsV^~3$fje_R}`6$n4O? [\\6`3) #b:vHC!cW6aN5G(b{aFlmlF;\\6C|h%TEmg\\g4-AH1Z{\"(e#Av) |m,_\\KUa_lKC2kpP._u6/?`wysy>Y|6e,xX?R;:S%3_X!l:<+7(qBV5Vhv^sp9WMhI>$6fbfg4.wH8]!gG|G\"yoH*nvdP&knt{|b+r{9pGz,)5x[[k;ZU`1E5%;mws.B:V~QiY*}Z%)/g#@s5WLqh9N[_S'Xhe\"8igBU\\@RY?Z{@%(h:(rQZlgUNgd`oEzM Q677a(:\"K1e&aa2$d85Y>{-T/e+NrkZ3ZTE'$qhhhbDi,\"js9K:0l/Oa'l tVw>v3UZy9dP)jG,Zcg[c/{\\LpGb*kq;bh^T[4adAKpx$<\"Er>9MA5fkqTg%`^?dIbj,!l,X|XPC38%/JJ:\"3~A@\"9q|#A8&\\\\V*BqsrO.q>.Gza2u+-cJd.F)>9}dIhYA#QQXDVi/`Y|VHuweLRwk7B4hike2!_xbNji@GV'e-rNjAwX~Ierqzb$GQUL ,.?QMK;'MfYJ0{.d+E&F_2nJkCjal)cei&H]fj34)'Or,{x:S!!GKbp@lc#gj9o:xLy@e5KG+bZivax;}P=`\\1^8g6@V:Nj-wr[e;7,q#=`8>SR{d^ Pl~E /{9L]+[y.;gF{kr=C'c:>CHFKHqu5Cjs&!}hhVi)q|fUPOk:t?i7Xifgm;eq`\"r1!Y/fkuDIr!+FG@//l`*3V&0A%WYutc4'>CyME'3DSf=$,nP7)f=@xjzVEf'C`=h{{E(J%ls>G4pF$eGf:m^3^MG-=\"JqwVbs[+lQu4\"h]ca`/Bj{2\"jfaakyaf~2}?d(w}- )W`Wdc}G5b8mTf{EwB_(010^y,0-}`;3'~m1oyI}8VrA[[@{~5J/L{iI"; MSGS[86] = "0^Gy|R.^-%FdkE::rokZC6k-^[SckU\"7C1]n?y1Aq4.REiF p|Wy#&r^qN:ngG`?k,T#TUs~VYgx]/xy+'Y=MfW_6 QGwql|2`fns#74hjAW7f.%-)JRj$=h8*pn9o!_Q}AJV+U^dmvj4g.;EG1QbCZEG((}Te5y7HD2_j=L#s#aDRGD1zJvH;wZ-0Xf9B-:au~6.*;lA;iHq,ZPN@`iIRm*/!hm+c4%^rcg;`jo<6u<|pNq]8yT:RLgYq%a7*}R/=rY/yfmk w*F]|z yk:5%h^T(Pi.yE`9i*VnrW[\\u(K|gz|XRd+m-p,aI0`#{S]Vo,+VlK8BbLncR)3*TCY!i5 \"Qg-vI-boqtyTXmd=V0Klt_$5JdeX7.T15[UrjZ>1pkVIZ}\\sUslrhN>s20Q3ddH;)6L#fg2T4z1[8^So~/[[ps,Uwp:1/2$7uao4XRA(O?B|%Y`*3k!TJ[oB*5U:G@=jva+]!2C/,o!>A]0C\\IILQjS3wQOy_KyVQ.FMc cZz{L(D47K@&@i{#My'\"'%Iq,gYmKM@M|M[\"40um&QQ~0\\\"kwLXSNo_j~$m^j6crh0leTZ c%r\"2qp1DMQ]+~3Ignlo{?O.3o,pGJ,F^9a.t]K2-..:TkJMb/vCz+,SiMdzSKr&h]&j]g['*'\\|#NOeKGaOmHph437*+|,Mzej#5v\"--?kIF9PmS8+=B,{8vOP,x7($W[YCvJvQ*Ef*#;(gt:F&x@ZJ8/{2K1|-ahD~q:\"Vx=[@*f{_,Ofoz&Wgr.,dN\"E8M2b'+U4kd4J\\@Tm<2>o1^K'xiR=6nx h(@!#p#2nHuzUsxo,k`e.S;O-KPV6%s/O<@r^CytKm36)qYhXHs@hE:.v25]H8/rKMte|Z19U=9Bb\\54CNC ~ns\\3>YAb9k=X/)#4Tp:\\iY}=Ab<_FXd(8n+'8-zuD(|j,!esdmeL< ,6nP':A6]/Y|?UzyEWp!I0y&d\"D`r*]I&c}ToT).}r(v0:rq$cPPN4VRdF7hcas}|+<_LGj\\;"; MSGS[87] = "v7>n$~jaqgL\"^Pf}1j8LtC3m+M6yx>@TkCF4AZn,uOP:y%-zL.k_[@ |fa0`L)Du!ig3r$IiMNq%2${3pL&j<9rn,DrRuA`|FT/OFMPx5gOjlnOe3'ESKIiliVD%t|2Du!.iJ~\\aX[3uWaS38ksmqxA*h=qRSe\\&W-V>FyJCYdcU<~}xJS_sia}`1l:% \\d%OhSqoR)2MP&Ld\"c};}3_DP/Vr{K@nl_}Fx=|p7@4/nwt,Hu'!D5p7WtkirwLj(DvRgIK.w/tdtLl[:zpf HV|;S3xlYduZ3ok4*0/~2|j`.>R&:#vv6Qq7(+oa~g:/7?{IQ%Paj2RG/^@~,@4B0lWR gd)qMAX,lEgA;hCm8bYI5!}je-EKsp7-:8*0ECqNp\\PPcLQwZQ3sDtV{_n#!D*Gay\\Dw)`7{aAPdWGF}U-Fh:M!qkL|m Gulgi)#9M>U,R/]C=oUzB:<'HRwL*bf8$wK-N19][cyo!EU!P!YY_;po&Yfr#h]GHW|2iTz@^uw3j,t84N8C]tK[qZ4'WQnmfaLlq)&bOh$30nT_hAR-#rlru%k`oW|q\\}uynqOAyF#^Y\\EK <+=sTkL8NQ5),m,dwV0--''%u}@Zn(NsQg>_4miIoE3v{r{\\g(_q:AN?zRQ_WL;BHs!ZBZZd27gY9_`0VT''2iCfwr6Ryza:?/l&w6P6` Ynu2gt`U3)%i'mkpwNB>#np[3Z6^fnRV/y8Q(|AqMDO9Il,AYR(~U<'|J>#0Xa+h>OMO.6zbBsrsf+jg?[['}w3NCp+A#}d3-@V1uUZVLM|bIHg>\\d?lUC)F{|W9l;g Q6te,p>Y|/x@7S9'Jt73n$X^L`oHC=$`C,EQ/5R\\F(tG$5Y/|Zizw.qhP(kWt}'uc1wB+G!Zk5F^FmlH\" )l#vbR0&~<)+cY$w/)i=5aW|C=d&B2c`A/Z>;P%1)-,B0xgI}Aq\\@9KY8w|^%kHkxZ+%-~P5MF7:wyos%k `Wj_*cI9O'.sgvRr;Qa ,O_855{nyeD#aEPc1X!ji>@Nr*XC9{]D]Xr5OtUhE 3nj|x>i's_$]&\\hBPS4?:I+b)S^sR^\"q0q\\B:b7Wl2n`1u#lRd[eN;+L#DDU0l=`Zzm~U3W_pp77x\"%\"=@&Bk I)ta'?iZ]2Hgy'h1~;_z=V_CS.RHAucHEOG2!kB@511]>8U@jk$w06sR4/Rr1|~Z%P!Bh JALwi7?v965g&+\"Hgd}p7B>0-{N>x.^X744J8<`p4;t\\=K|9A@4$u=kz!jpbmY8 ,BH>!) s1w;GuNRTwBy_l.;QFWqg4Lw*w^SM ]KYi7QsM=*N&Vdn?y$~dl`IOeNPm:E@[qgzSI?qg~W0AQDC,>_f'Ks#'C*)6JC:bKHt0}PN28Hhw/umbQ7Dg~zdvu^i$`=STCcnM^Xi!7JiqttdxeBb3|!KnZo*nmKN+(R~!zd@Q[\\w!M!]R\\fR2gR3b`;qEDw0=STuFyvflh7Q\"Kx{nb\"~JHYe!&\"U1ErTjIzYXFPly2/+36SMp27>W;IHYP?Qv`~@/bk^%vM/7J+\\qvkgDCN~q=gS[2kpHBFd_4r@2E,45^F-7e.0h9y=jYV-2i l|`0',aM %>M^$iZ)y2@Rp@'=y-9'lmOE\\4?HgW5kU),c>eq'f*ok{A]W!$.h`DZz'(}m\\l6^+K+xVoEw.vKA|8qDowt|I_dEapX}G4MUVtEqxuaOOW\\:a;BZ[,7[q%<5jf7+AuOSZRG)H5Ul:H 5mmJ=Pk=8-;J.>p[7eQ:Ub~&Cpl,T?XX|lZ*,r(4ho/BKKuhjdzG>34Q~A[bIw]O|XI,:F,kh2y(T%/jz_*qA/GVZSgp^#@cr,pLcf=!L2=}g-S-\"Ow$vOWO:*!'Tni\"gq*2ZK[5C={^}\\uk'?T1MfJ4QrA'6X$*8/z2OT?V*!mPc03\\0Xzx>@xS](@%ME2 '`_nM{s%gehpX}i8$rodVLPq78;yQ^@L^Jw+OE@mm;unZbMh(l$0cc!hdLh]>u]}yy=Wt1{T5#fPXrK7e:GiLPM|u*Fc]\\H-A+-q}MMMo3m vCw0AH`d,tluPRM8>&-$f3#^.Yu7sx+Q\\_9]M2whQ~::m'[6b4KjzBz6lYF)'z4W q=VJ[0X8:#{:a*syk7znLos%|!IiI$G8J1VB`GnQ<tfKejlFxc4{S~VEa75c)J9$XiXht`H&%TvTCAx,v@Yk]a:b~h?5}\\+|(4'cB1oZ)GwCm\"hWfuG4k}>9`4R3.reAF<9hyPePOeD-=_&B^:wf9>Az&x.N6DnT\\09#P71 uI0p>9)so5'zwdRwDC5Qi:4k\">kon&#a[0S:cT@Pe|u?lMAp(ltfl|e?;,3`.1SI~Py/Pii[?{M,_NM3IW&?p;0VtQ?DTx/7H>wpi+F~t0PW:}wba=0*O?n\\uep\"WXCitmwRu3@EU_Gt#rzMF\\&-K6T5iz%-[Ebxu6uGesR!}aw5Y2jwT;^r'% MY^LxDTV9AJ!|A^,xo`)\"(=?p{{16._\\G?@99DY?t51aq.&bPANr!>56HlD'x#fi,F\":=X-@t8%.z,Uee^~,GJ_9h$+Lr@sCcE>z-i2}d/@9.6\\GPD (4c?&yye.stW v#1aw0Co=iD_!e;J)aUF9]kwXtG?6)TMB35B ujs=7\";] ^u4rfLaBS9Dy5omelOiE]&m`CR]dD?"; MSGS[89] = "`==Ae4_s94v_|?*$QLvDvE!:3[(:k:No(IyB+,{eN'/BxX6*'&}X*vf % |Ht{;]bkwEERJH1q3MBt~l3 [V/%,$qMjJ~+nwN514Vp})\"){MSi#[:`{.f-\\^)i/\\AcA$wIK(2F7[RW08eK[1jqkpk-IXyZW+OWjS;Gq&kEmGexx\"#-:F6WO!-1s`{$cQ:V$Th1HC#G%gbIWFQU*vf[RXZV%J#>e4an#:/yu:?BQCX>1$n!!I#1!RdX/CCnCwO2}`Dn: pc/lJ)PQDcV$YG$9#^%MwRIs~u,XL#Y0,&MJKUS3!o&Z2pGISJR%\\'{>v$\"2Fz?u~_|#ImT2;brJCK23^,o/q$QJiDC@3;Y9lA`39PJd.B;.#0iSj4V!`D}i`,^xzmdU<^'zz],BIQL#P_]~TaF$0V!'qr{97f}xp2$MQ@exThy+jTl_r{kC^-^O;PhM9Qx^r!#(\\-qz\"5<;C1fiSsKH w;GlM~WSn-}!WX+m<,q9O-g2S$}JR0*x_aE+dx=7W(IPLs&SgA+@pHJ;ircZ8~7}4Muk*?x}(dn\"lEe${kLh|LJ9 ^2g>'I}3j+idY SU'h~L7hb:oP3iFK`Zo(\\{kE+?/Xi>)CoSo[9d${BS#LPq'kCp%N%w6=+0h}Mm1lgPK0/,Vs5kg#N!6YI\"w!kL?bO'5Zm_af(G:mlkC^4fWY?iH}2=.Q,J(>3h:=`>CS[7X!& e8*BK h|A.FVG_rB.z-`246zE}qPq''rx]/~BrPs?9[]Sj8~u{{_'Zy[=Ez,&\\yI:h4/TiKZ*%d\\,BW#VF8BG]^+c]B-^Pw}W'jiI q&rzEqZ+Il6f2SV1{/U%99~<[rE GYHrTZr$-p%3og@isF\"'B|+t.m#R!gGh*8$P}tVzlphKR]sM)BkS!.RI|isU8Hrgifn0Bb?r-:UxKe7p=|TJMJb!n7h^4QYt&`Bhi1rL05m*Nrf~7$og{8!zTa!yQe23Wu6K\"?m]%6m3sjZLQCKRjB!>ytq+-oEV?c)MoQB/TPSmvJd:WuSF$_$3b't9q(3@}o-.Q$b-\"NWfS#Th@g-<%(|U3=Z G~%sdkPa4+g'5.|s\\=nMxvDeW+Y$67Fjr7ut(V@p.=T;XrfZKg)>:&wYD-O]*jp%?8SWLjw\"O#ov&4`zrK[{\\kj1YUrxK43lap)|r]R~! >$S.|dWH{71}wo[m~uP+$14,m^k\"GNLw*m/ZmOXEuX/\"\\ASqkp~S 1.xM+iKcvJ9N\"A}/r wnx~F%s1O,'8,F4hv[T#gr&i,)5@;lU.ST/xl}b/_'x@0CCD7LV50D~L%5Znl=5R}Dbct+ =[12%&!(]0y\\)7xKAp8 A``D{.6bmX0UDA]'](IQH=oFM%Y}cP=bS!=P-F<@i+vj+dxi#kpN5f}_.%aZT7:(@\"{RJHfDJ(:D;:t(QXIL+XSYdr5I{$aiYmJw\\s#{4xSkLdpdT]Ej!I^iFVUP/!`YH'jFo`{L2QnpCl27R/ZR55j#bNHQ^`nNH}Gdh\\oZ{d/3Hs1o+;HT-4yeJu>H)U4x4$u4azO'eMdLKL8Rg295GZk79-[d'z#x`4&>`[9'Z*BtSA309FQs,vM B!d{C!V0`'fNu}A4^U6!sNTAU<;Z56f36R`OSJeW{zYTPQu!{|l0Ycvm:N6(v.P8K|/^%L),D]AilDU^7Dnu@p/=3f-E`=:3@mrX]*-q6{FUT[p@&E\\B2.}ih8r4871F|Z|5Id4#YH~f02E.zl@!bE\\$-=iM^qb{0=91Z=Ju8JZ!I4us@yZ.:o`/zOJ{`eX9jp=QwYi8qw8OO;.8Rx5KB8]!();r0?:rTnSHHTBTaL=dze\"^ITuP]lbc!Q2]4YDR*?u\\w}{. \\4pww`O76Gv;Q0xVtR(Hwm!fajPa9iALM0Q-ypW ,{]P@Pt^IGj7FTfpR[cC?z#Y:75;h2Ktk]`,jT=RO\"J.{0Ttuccg4QPX\"cy&xvs`,q+vr:)(\"HZHQ\\A1S83s#\"K1- vnC{V/rE{eb7#X~_>$_pR/3V>@l#~$Vd;RG}s<>KG0.=m##^'MtWeYE36/B.VW/\"W%\\DtneWfNd Gzp=Xwf9lH2Gq?.c1eD%yzBsL \"A4?gxr&?D0[#rU05h\"G:79V:q>do{pI$#3||+}2ceF2ir[C|T`g4^-m#DW3eKa_%(}k'?i2|kt1w?kL1cI@ro{!Hg9`k4.j&Vb]u,uyE7:uIo\"NSX$jIL+q%oB-]IN9.?>LJ8SSj=y:UqDOG ifHqAtO$w0Z*--Y)Gc[GIE58EjZ[{_y86BK{8d-@O#ldr\"@T1|oQEZ_w/n8gj/@Yt5MoV,wPM63N$1e)&G)GrF\\,Bst3=]*4nRD}T-}a#[*[5?$_dO;{)Hz5l,gu>S!&KFE*Owy.PXM.kf09mOpa@OeClz(%;(O2e^dh130?s#Vnh)rDo7@WB0.6K{$\\&y+`Ikp]H/k$nHRYr=OM]geeFT\\*^`Uy$YM;g6=Ii@R#~IM+XD.)Uud!I|ekgq :bZjR*n}Zt>Ogcs5d^3-ym75N?2ITIV!I]=Lc-^pXL:O9'1acM9:qB^A) &Dzsea^}H{,v/>kh;SW51vxiP%_P2Pf,#*%nZ>1.?kGXJ-GS]s&32RUOqjqa{hyZvC}iTC8'#f#y P\\Vl*B{mHGsy#&|lKx9Up3Hjyq}s@[ER1jvGj-}"; MSGS[91] = "FMFR~'R>)^DGmh>>8:5P<1u$gkP*7 +5U1Bi0fOB|4'lN?x|:n1s%\\uyLMj?9){P:z<%Al?_!)[v0dU_P{Sb?@N$wfPeCO>S^,^Q0E9Ln}s\\i]xU)la7J'+V]]px-j3~}^>V<4t(G)@(T\"ekV7w)uH+re5sdEBMc@]38JlEOjL g[id{TC(FqQ^o\\Zx9kW!3K*>Tim)1\":4?lBnZ# dnHjb\\8w#FMO@`Ok}#CavTetIyzt`QW@LH0},=k[1(ua8Yx$h2~xm9ch[p8`#\"MI^MkQQVuQJ3@T1fw&Bi9}eb[%{YIp&M(nH7Z0jhWG+cS;LH`8GOhX6=i2yrgf!?4D=8EiC$=Tf+k`@L\"D1x'kNjlV+>ZS~aoa6LmRVkFaTX:GTDY%'cJe4^{jQ'D8/l>UssdfIaT6}?dxra=W@OT0!D=f4.#D`lj\"v3;ANY3z*R5LcPsIjTsPY'p~4E_jy\">I,(M.VW\"; k5*]V[_n~__j-I=p%)=;J[-Eh\\~}aG\"o{OV5'RxO!ZW>3p#/feTu_pj>eO?uC+l[cWCY/t4LQF/w|U43@[{{b0lcHS{>v@J3V?H =nu3Q|db3X31'S,U![m%Z0|3iF48#t| GW7V?ZJooRRu%H*p x^+At^M[x&t|15Q47lsE,4]7XDRC&ncVzs0~*i&^%BU4MD<:9x8`aj2q.9%E2[y^EZQ_qX{(D-.:9(@xi%=F-3o L`fRFr]4aV*cmi-1Lqww%bxe@tYgs!:L:\"#(Lc~%42v'+X}%Ai7c:kAvMpi&AYD|0|AbAX>ez6*Q'v_NAXNFoIo3&wv.$y:OGjB&[\"K&=P)HH=l#O)u.Y(C5\\|Fvv8<+*Yo+mV>}%)V3f$@#c,eS.mZBV_sD@;lbI42z9Pyaa49j_S8>7G<'c!@=Eo7]h~-!wR`/Xhq%dH^s(WWgo![}C#[cb,dhoQFmgX41B]|9Xe+tY- mY`9I2^bPQ1kglncz2ulX7dgXFy&vX\"#jXct3gKNj1\"*Y&fXd N^&M~rR!1Y/h,eokmPkJS]n7yPA&5(0)<\\|id:'D;-F6?|'%Tj]@q`']Tx(Q8BT)#]IbVg(zoL$&&9FaY8=mO'vIS/\"S-Wl&`LB/jh.@Po2Ng}|@d-HVItZ]Mwaj4.=4E*qZIn@ALT+;^KnxH8TZ`77&0Z#iv*Ku|{"; MSGS[92] = "\"n>V! NJI?Z/my`~avF!)g.@uvjzrT40i/K~G-FOR3rw'S`Cu/R IMP\\{.d#7Wo/y\"[cTfQbi;}Nj8=i+`N\\)x\"Ea&F^>5CxKbA *?T_qruD<.`*ojPjA)nZOwYgwn(i)D*NZ(R*{h_\"q,('H]V$Ot^#2Y;3QAFpC&PUL2Ktv[2G~*NH!=db;qH)>F6*oB.v?5n>2WxuDQ\"<-d[RVuyFDk?M2Fl0pu]]K3l.zE(!]}{1vsBp:XOHt!Aed4oO0O>X|TILRe|.cEWZj Z9d,x<1k_l_~^JJ;._U{2 g>sXoe_47ALt3q4HdX:G'X4p9xW$0FX89qMIe4BcjP\"/K9r%*1RJry=5;^Qa_]WN]Y`-5\\C,!.np[-@(T5Row/Z8'[P=7?#bs[0j,\"[PFM(I:gUfRCXU\"\"_KKm\\b]q/IYCCy#;v:*.~-Igu-wISk1SFF+6(.C15a!nz+05yjRf8v1b MAGOuSw1ldR-80TY4MYjV^'9oOI-_x8ok@xL=K6n-Ld*EJ@HBSKWIZ%A\\r7iOGUZ=I(`.0(K,MW.>!td+tE2&;37--l~o*T{K~/S=KKPz~h1`4PdtNeRXAm:5UWES]'O?dB6@XzmK}_UU]Rz# 35sSU'FN:E(6V_/\\l5^p\\ul69V!A,5hT_Kz]p]n1?_TDUt#E\\OX?Raq[iiHBu1{y^.4WYk6&~N*w671.Q3OK:E\"!2/-ej}+)Lbt;~::DBrIm&LV;T1V/I>|K#VZO_QmUiv(m^t`SdA'^w0F(EX@ged:]=_A[=G;\"1ojzzwRu[*PR9Sv-*R/P0;-pEDD4np9L0@Lm=F`QcKY!qbK;/#g ,gJ)3i{~$dcUi|lq\"kRmF$Qp*$m&=t:&6jw_t?qTO@PZ1Oh:>6 s.$v'*;Q/hlwgah6)C4w\\3CBdtEmFaC\\hW-HH?ta,vN(CPthg(.Q3cjbfOU!2U'g~E'`Py$`,KT&1GzIu7z[276.y6l%XufC* *OVj-Q8,p;NY;D5qs'd}}rXe#9=|_Hn0Y`ymy:+-8lyy>IVf!vMLAz,P3:dnw4g|h3dU6,pT+/+^I_`,G_=!K[d5Nw@Vt|=|sJ8jz#3O$~8\\{}ZC'W1:6Q%}&,T'jSvP|II,2(AI-#=*DIn\"YVQ#O*UbKJ`)W8Nso y\\WXbk`)y'C]{ j%dF\\zKdV\"?}~9cu{M5GKyHMT6EuQYr}{@?BWl,S}]b(Eqg!yj0gR-YHPr95xm5yIiH~#}3,kA#Rbt{N6n5$0|M~snv1B =`&Kk}8Uxya{~vN2oCbQf4K-*m fx-3g@]P\\7M+JB}tDN.cG~I_\"E5\\ ,%_,:=H (qPqmhU_hgEle5^_G$SEe>\"!5m1U>.XaGxiM\"KCiUU6:.F)(,/|9KPe0%:~ICaNcg#~3n{c0$;`5(pF>x3LI+!s)1!y+)}7?_HyjT*qHlvf?O{16PoI5\""; MSGS[93] = ">N\\=7V+{%NDJ^]znE25e(uoV$ir3FDL #`AB?i,a->9IbKWh=Sy-;SNmRBg1'%DzNJntHj3oNH5,P=)8Sqm),ZD=FpaQ#%M`15X'd+Ei=:N{P;]69}C}1hi/9_95M\"EinHMw*r@J&4F.Ib(`esX)v1WI6BzWf4:a/NZ4[B*e\\+els`WYp[\"[Fs}c66(rzMv\\1cM7K;JuwA5(PCu~M.EZv8~EY72-Jk1?\"ykRQ4-p;F%1:hJF!j.Bb^tCd?kay<[>HKGb\\Y.-v5Hqa|_RZ`,&w*cH`JWq:$ynk&Qyx#V\\bs#]_Ok>GfNBi9gQ8:eXscPwD,@iOZj(hK?25Sl+,wz1/@nsoGf;GB-GU7Ztu@QLQZ`wE-2.^&LK7%J`@ EGv)2:vbB} z/H;(h_8|TwJy6xgg6}/ROzoz[:`f?:%S_FSJKd#(}>:Bwso%!.TZ-%tAYW('TpzO|8-i:vMzDtil=uu iH=iB4sJ%\\!*5Flh42m PHQ]q1nOn\"&1?t4HuBNZsJ?t+/C7,e)6jv#5FZT!\\r|QnAIM;Xh|MeUTuK7B:}v/MjP5SJ)|QMefs')!s4=KRc7NR1uo9Wck)A?Y5`zPhS90&`][.2dw$/Y4;\\xvdQ4F1c/[JD\\bW&Vj84q-vK+7j'K%-;HQE~7nMygWku[ORK0fbcf*=C'QP9&VALjfsBglP =o\"Jh}>N+=RD53@u|;:b(J#U0xoTg-GvaK}Hy\\bukwyx@@zQD~@Oqic,#J:iAzh<`22o8:P9Y9Z~*-xE/>GY\\7[fe%xDc8Edeb!' 'kiMw6h1@fo8Fgq\\f],1bS2IB~U..yT=RE4R5mGlZ6I=Z*|5WLQTPEt1C>ettP3PXuLPWU+0,?A6Y~$ui(49u(>?!(P;:qY3?hOJL9a7i[0~X}jwBb#A\"krGk/Q*TVct|Y(fReXQN={.v8dq(FwaD%CO8C!'i}\\ByJuW{o23PQ-IRgHiD/ IGVH`X;2<[?Q|VODSY82S{!z+=5]'WuH T{_pL/|!=q2Q1l?FWt;g7KAi}Fyw\\o4_b+uqy;?`h]u_|TOQ\\0j>*&\\,Ot'B|{\"fKc[nh0*F>`^sur#NX{iM>gzyH;so%7wLsL^b5l-vf\\YKyTlFcK$pDc+(Cc*FrQY)dX*Zmj&A,F7*Z{U4@=yfL=a_#h+ru]PSU~IRMi@XQ[b<7pM#_u}a53mhs{gn=^];~f:&#eQRW6p1:\"iGCUmj~.*M.u64=1(n%}WwR<2gb}yFb$2kYRgqvBt6mDB~DrObiWjo24\\9k!CNyOgd#S.,/y}Z[AI'Q<{1}t784__M_J*BjPtWT8^+*/=#sVcl9Ns-xxwZ}|w A5*QP^}2&CX<5m[1D7I;|0(>7-,A)IEQuW0~RAAed%/qfZ'=%4P*yGz,dE`dt[/ht(L:{IVX6V\\2QI(vh,i_R/"; MSGS[94] = "~@NF8Gaxq$I2LniJOJe8=k_XQJ#QuV}c]K_#r+keDe0m'\\nz==KhHz9D*6l wmY\\<=R&FE6/d6eIO+2\"jGY+Y3;W+xlGv,].Ub[me0!| qX{(d.>\"WK?'Ppg%Idv.c,,v#GP22f53#XD4sg\"2,at;t9@=ob$h+mZ_fyo:q#IcU4\\zrIHjKUIU=o_By?0[U\\6PZS_S!NWNhYIZ-s1~qCpi\\&}wD4FuezNSyzv]_Q &EuG/8}tQK*x8{itRg[L*fX [wdR&\"vhw.PJM\\Le)9uC?%:]jiI p?aDr{z+fwG1/6^j4G2ncw!^a.&eR!]TOFd{v~IH(eatskKdu8?\\TgmG\"Z%_su_?j[M=AnhnQ^L?&>heZudXKS` eWt~b3Kx`K,n5 ri~${r&p%4n=v\\M'~pUk$Sy0R)06=sgI-]I9g5t3(\"W`=ZRc\"w\"pl){Y$GJ.G0N9~cc}/e;J1jKRG(VQ$Lbnm7f@3R]-GoDYmk1an^mV>dD~J:a1V%Da.@hV{f?9>THLwHcOeX?C@\"Y;b-Lm6kSyo%dKr,JhfI_e;~ST=1B-:K;3@]8RlYI$>jCcgh.drBmPNIxa:.r~gMEC\\%z7|ap~7EsAO%F7RUFP_Cd(L2#7\\q+?y6b7iz~buq?<:O!MGR9bM=NQAJ5K!ok_frCf%Vf^DS'3FXZ({'j2*CwLP=z5zO)cV{`2HgX;hxJ*EFRiwt>|jwmS-.0!2A|P~=.Q]G`jt2#sp/`Y;=)ARR.F\"\"wW/zB4Rncv$F5y~X4Ou9!*h9K_115@\"^#_}Jhi/>m.lg[z{Ek1&y '-r@oJ>:L^#n_SK#JLwsM~qDFJH@!/_/<@0OA^(-<;Wyax.Hq$ )hq}gGv=E|Sk0G2w0-^N@h}RtRNZ)Xw.{kQ3`dm%-lX\\bubU7w!6DAFbou1$nUBGfHl@,q)(bWwc>FR+;XE!kkKi^+F9ZJSZb{$HAZ\\,e}uno4zj$Pv0HoG030n%V5XnlY-{HZU2?=,9rIvu#spUbeoOWu-jV2A*8sk\\Eo=0P!g6l^XhZgA'aeT9;I9-9ybR*xi>Y>Oyg(5;KJzk@;4}8.0!twP^yn idH`j7O1F@'xcj.8`;0wPW}3p\\7d@_C(B-FkJ~6*p(tdA1H@#4+uP5kXE>x(My3f/Z/|P67qT?)KTCxDSg9$7*_WvUjNZDmBu?*l<$Q,+)^$ODmeM#$jMc~v8qUI-e5rkT(I^GzzE\\_2q9(,H`&fXN8QD!!{ez-#3;#RDN/:p^\\Lc`4wipmQak9.Z/ih8t$PM},P0k-qyu3/BkBo( DDHC{^YrD?(gm`7y1D/C06?lifo5wP7}vL"; MSGS[95] = "L]{J7LgwlC'CC)`V@lqh0a 2pb{0Z|Tl2Fk^*~:-Ex^'1B\"I+ e!m6B`%E5'~P:u\\B_Va$5ph'sX!@vH8-rG@C|dHSBX!M$'ln|4g4L[QjGLv1l#pmb@fQ3(\"3&S58loW(g=h[vow#M{oBIc,67>\\*yYX-g+Sb7<\"%|/D9/nY5c:=w'#Rcv1-S_X5}e{K6j04#%g~vNp4.19.&}7jw7^;'&!GA39+`!IMTbIzNX(jD.y-Fo.-t0\\Gcg{)o,i5mD%dv{vjCk'.'oT0S|\"?KcV(?5U2W1uqhCWp;}%Eq1b+oI3akhbC)=4Z3{Uf_)<4Tp CzYnDCJ7:9o?<#i&@AYJ_WJLQd^nZ#Sv8\\p2Z+]{gqb]?@@G-4/#|x) ^JNg,^6.(Ed-&3X8GZ8`Sn)>M4+#~}w_mwJd`y#{MAub)F%LKsJE'YkojFu8\"92H9A22i]X&g1e<5OJm`|-G XH[UA8=:YPEp^;+(D6bUOb-%nI1Qaa,6)&k0e/E+3gOJ&H}^cfa$[)K\\oQi;pQWaI|D\"oX)y)%D{nfrFsQN!&T14akF5m:t]Z^ 7.A5h\\b,U[(M@xh;./)6Ca{]!vF5#@tJd(4)XlljHom-:DUnb5M[CV$5u\\@rj6#LStv\"3NWj2SVlPBGhD-~~}64 ]G'JqO3f#SSNngaW$$`7oT7K;wauA3I-XVGbRXdbHz}@huV]8RXrc=T%>.qdFtB5A{Y@;TSO]rRd;YOKW#h'Xa~[fD:/Z6p.E2e,zRH_izIk65QYhn`ID+C[e#afr%O-a.{M>y6_G)f]1tpH.V~@6~)zAy[Cp>5V?Z,>X*\"siUz:ZjVQl$#^L;f3\"2r4M5M\"N'G]}UueeWmO3@G.+onwp\"XaAlT4(:=;@+gV28,3oYjo$]dfC`&M@Kb!/`?HS[\"l^Iw%jHA119l_bINUHvYk[{]kwH*!b|hOKl\"7+-N'dQ2?dFE!/&:v7N}2SZ1vM/hmt%Igmv\\MzSj6`62'.yVODd7NkZS9/OZB7s!Ros=O?CcLii{beb&(pGD~ZqcU\"t${muxB(bV}B!`BE`a1dpj3(OaoEgJ/xGasKs>U#)cg8D,JQRd\":LA^l1Gu2}0uBh7|8vV&(fx!wg~b[Ko\"BRG})*d&1+Y"; MSGS[96] = "[6)hf6YqrSTHgs`4?9Nf`H%+j&NRWGpv}eXuxbaTHDC(?Rt)T2wC2zQSR+-obk_Vz}LdX?o:>HCl#\\1K[e\\qEP@bicP2(|zTO]#!rp3O[3+kB]YuBK!T,)XCF=SO#48=HS&76.f9/y=ex-a%gQd`SnD4A7#K^U^UA6w 05z>aGdUj`iGT8N-%Ch|l,5jsX1:rZMlT8,liyZhK\\iZ5/\\}yC*&2G&)JX!L8qL@IE!,GO;@U4aci}HHs@hqO+9tSZb1TY4htV}fj0|nMcD~5\\7VX<:s{*BsfrHkB(ZRTCQz?MXdo qfe{E9(xb@ET@U7PLk6nm?21%AihJczCB0`4$~(:O7#H0P#QAX.K4_)f(Ja{vn!*znUP|,ZY_B90e+pLvJ_PySrxcUoXN#K*Fcak~ynt3)Q2Wf;bdA-\\us)Hlbs 98qMq6O4}mO\\fMw[aj)wY.Hsb6*'ek'OVP{Po.>TL%FcDn&JFb6Gq#S%IQQ|&Ikgs(u$A!kS]owm?Ta+CLf+ *6{'sax*-GPo*7)#2B8e0Gyu+kR%hty1 cy'Z?bk$i6@ui/3O8P3\"LkPF-VOn4VY}'==D lwi|!]x28]hdusRK Y0gRDIPr\"oFrguN =UDaydskO%a=hxw tkeN@T:dKf;aB+laLg~eqz< ,Kx\\-2b7v@P.j<;IK~]\\ 3Fv5unr7$#\"!XmR=Lf|,)/0qrjfi] 8L>4ANz(zZ|zO3Z'/MOj.K{Y.]Tvoj2K9E5]>Y,mEjLU)?`=H>!IJFWua3!r;_>%tHRk8BNKTDi=@,6;v=\\O6Bfy>7.IyW:g/CGie:D.eeDc~rN[bMg~LpE3'S(6Mc5i{b%@;>>Ih).k[$h+Mw)D3~!K@ qpjp5BNi>85^!Gx55vd6u'Vg+uniZm6Qp\\jq$d&B{X7>@]:Zq6W(),gIO>EI\"}[U.Qc.NSsJGg&G`;A 8U@]<.H8p4CKGabw:;Nf#kaNz %$<>jxDe^oS$00NF}S$@-w<}+9&6{?VgAP,RT\"3vFovuIHn08*n`E10WUrrDA} XzMdzK#_2^*~Vf|4sNKsu%dXU 92tz`,Al_Zm5i7f?JQ7 W$;hg^/5r6ISAAsw%>7u{i2g$Cm35@0+7w\"4M~GL]Dh2.7^lIunbb_@(I&0^3ouy3~Rw}JiiE`D;dKUjW6Fd`#q~c=PX]JpstJ{;@,]g#Y,nsl@-^eTp5T]cEAwxK(6.d@=hG:xXI\\i|,*:$OqAWV)(].HSa1}BBhhYC;m5ys!;63nFa~BoWk6&V&j)cyS`}nkecjhvt=(9/}RFR'#MmgfPK[MN;%=3oi$tx4V.$88~}2Tl\\I5O\"J/PioF8Ike12Ew$KC\"0P;x1jPmnVz_vN\"M*FW<{q1A+}RReu/[1CTgNl1N&|#?lhq5*@|'bOhCPB*Q^8k3+z;jPmEufV1b8-$0s[r@lZAIY8=W=7DV\"I\\{%Pj)a:08nTFARu9K^!uyO)zJ.4lg]SXU+xQpDVX<[7!.$2m+vGT-[J+B{Q)vc];)>f$u^)Zo$Q)h bk?Bk+dqioN2]|s@wZ|[&.PE\\Nu59ZP6=vsKul^>E17|>zbCpo6%&,R6=zvXV'@o6o^+Cn`4Di(0 x+V3S<+Jcn1{oe[L32!vEj\\Eb9\\}'G;4d' }@#(ul\"bZN_}&T0d[C[K|2O!;k.H%L6%Un\"l*56mr75jiLfGXG0*W.Z4_C+puG*L]MHEuds\\_mXj6>#+=,cGK=ra?AzT/yC'jCt4;/xC1vjXGw+w9}*\"YMF[PpRQ9m2^T,Sf-Rr-VtTq2'@'pe\\YUH@R55Vl0h)52s|\\fRbXu>KJjH;lnc~^|_?iOT?ZdiyO7nH]Q8$=JS_72K 3mB+WSa`F.EU[_gW3U.\\`J}OBQw;@<4IRMG''>CqlV/`02V\\}]&wuuH-G,!O8ip_Sp7Aq|66Ndh)tmM`q%4OB#K%QMOvN*QK+k\\ufuJIMh}6IJEjr5AhTROv;%?lw`W0$b$`nIh=JuJLN|InC6{EJKTVqU{+3i[Ol{@L?:d?KWJ8pIdCOPnm7on!dmZW|Co}<)yS_C;(VTkeoV~'7!Kv kuBq;Ha=HB' V=Ve[c@Cr.E_'14z2SRY @1BaEosFD^o4_BK`7pe%U%un9-n0t'crZZ>I~3~LIssN6,&>*g;u[PSf`qBTlNS6H1Hfmx.=!o]{8{=l;KhVs'PR/L^J6^b8q?c5\"F4Qr]7\"4q5Xd^ub7@F!gOMXs&qB*JCuu<0_OAx;z!b{EYSD$j[_~!;_m;\\dQ3H72DTdV1>7.uhJ\\Y0@7Z09I:Vu>oi\\ $.AHMhWfSMvT;=G{v\\gm3cR!}@&/TAIO^ZGex:p&aA+c\\2:Q`?5McARqPIY1_uye}Uy)yi8B5wh6+rbE]1;eaZ'jz]]n=?fKFp/yvl@Gd~\"C0XujPg3#;sxD{X/y?\"1\\)X?rx%Ttbn8-RHQ*%Y x}yclcGFU8)+Ggxc+!(H,S[wVqS4pTf=_L~|3\\ NOce\"KULXR})_y5%yEU6\":n#ary[T,{PUv\\?'?) 'e~x3|bmYKSU[X]3&q1[KcNb{1rNZ)JoE[s`F$I:!N=CR@ [PGujwZd/9g"; MSGS[99] = "U0JR[](*;~i*-@]^VzN|E[LXdaAC,A-h'Ou.S+`[.,O^Hu3RtMWF-X`JT= sJi!h}}}P:`GPhZYi2dnVEI}ibMU! '!gXLZ'%uukP-3@x~B/IZ, qZ~}A[#6t>;&YzW8UuSX5eiS6~6XO.Jh'?zdN_khst?T@ -Ba^4T@U6#+-=g%/p=aOWP|e:Xfg@>AqF\\IR4i.jo/`z7xxtBL9H/qr}IzX1T*X@UTe7Fhd;wk2x)Tb5<1O,f/N0=@$b%{-\"v6_#\\XvG]xIvZ Vd}P80q=ay~!P7]IkyV6$dS}$8G:zE3rh8D3T{yZpjR~.&jfBj~oX|4oC B}I%^IcbE-rB[||$m$sh{c{6vw(CU`*KC-Hr\\NHf/ef.RjUBx]qo?b$1rK9#QE<2Xug*G>~FxWZ>0m}WK= DTz*_'[7beItb0t,xO>vG_)JF+b>;{B:rQ*yrbFq-t)P N2sZ*8rFWh(K(9=-C4UFYc7V{[h,JyzKY8~*9!vWs+n{_(:aSV:J_kkF!y[(p1:8bP-E'sh]3&f|3,X6u~b)ikR<{uMqHOBjw'.H}3(Na'WI6Ii9c+rk]ATqwLxYnu9(I}w|*sr!X`CCTvW<1Pk#:@c(fdl93\\FM\"rE+]F{5K1ZU.OT#Q!8Zs\\C_n*swK9.jstR?VaESJWc]l7bpv?Xap|.A$[E..`&Jggq`bB2>'-\\9[.J#C1XKg2$9mHB$A%\\v-PV,^(NT$E:*)ApP&D^,Pv^et&|t9wVKeCg*YzjdmTD+;kn!Qi5._=1:-A9\\T4MTvCkKzT/>bH6a`|gU>\"S0asQUB`lT=lr_w\"yG5O8f6BJ4McZXdK2|1PzO%k(Unn?UN=(R '\\knv=hHo^y3nOY@2N*WLi:OMX> X+3K]_3L8g-|/QLV?|Ow.cp-^xbp<[(2%}o@6U?`[Y0s_opQPWb~l+FPR~-qCzFE'OIoPTTF!h:+q]CPCT=XCqG)YPwZ^_a|yCSe4k8L`'r.l/<>HRi-GG1&eN<|G.G?qA=7lXIsvYnWRyeq.\\%B[F\\NvB3tHfEcp{Ew)>NYa\\`nv|XAH|#B\\}!H\\RE4B9=k\\<%\"-}$ukcsU3[oo4auhM.u(G>=PGc3=>S)vFAT$\"P/,'&X&s9AuXz]&u:|*LVIP(,@1q>p6oF*^rw8Rof{T!x,$0il_`MzgqL6da2@|9ecO0XV&6zx/\"|u9_`wXpfOi7o(6gLK)p;AIMqA!]9AE4n~}S`Feb*c`4+|V6Xh=F$[5_Nmo^UCX=Biquv/Wf94Dh0}|}Sd(!KO,z\"fwtk(zWQ4TID)B.6OvAqsQpSfV\\Z7O1` ~[|p8w+A!9hW{jOn%xTC7jcvw]'nA`1%inAhJ6.-5cs,m}7dv\"}b=ia9|at#4c~"; // for (int i = 0; i < 100; i++) { // System.out.println( // " MSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(RandomStringUtils.randomAscii(2000)) + "\";"); // } } public static void initDIGESTMSGS() { DIGESTMSGS[0] = "xzCqTGj4QwssbwEhsvAgOSXS7Ifb22r0"; DIGESTMSGS[1] = "fUiuoIslrOutY2+7+x1i6trJq9qZ0fr2"; DIGESTMSGS[2] = "K6ByHx+rSFAIFGNs3klrUNrtWcotAww3"; DIGESTMSGS[3] = "JqB/BEJ5XJCO9iQstQsEsy7d8NJMCwGr"; DIGESTMSGS[4] = "556heFehnZlJcLxOH4jSlAiB4S4CnFM9"; DIGESTMSGS[5] = "D+MQ4sH9AqrDti/AHWgTrX7zZGtBx4ci"; DIGESTMSGS[6] = "d4Ho+hhwEAF8WrA++tQs5pyRi1uuq/0a"; DIGESTMSGS[7] = "nX6qt2gYbFN3UE0Cs3w0mdoCYiUp2hDd"; DIGESTMSGS[8] = "dnFut8NerfrOjz7S4vCk4htPcMGj/foU"; DIGESTMSGS[9] = "x/Y3iou5Ju8PgKms3gMe5R36NtmwM07J"; DIGESTMSGS[10] = "HOBb1DfmxXJK8VBKiWDVYuCjUFYZR3xl"; DIGESTMSGS[11] = "ZyAgVQNNB8J9lGtcC7+nOgD+c0wENkIe"; DIGESTMSGS[12] = "q+9uc5Js3RslcL4SZc8F6yMz+IKVKGSV"; DIGESTMSGS[13] = "bHNKJDQEGUxD28JchSX3U5rpARciZlAu"; DIGESTMSGS[14] = "XsWHO+JNso1fFkcJjLvXVgAW4I/zCw4S"; DIGESTMSGS[15] = "Vvsrf78Vvdp50Kra4ndi6Ik/9WWKOA9T"; DIGESTMSGS[16] = "fZN9ob6RbY2p+maFlRvCKvFDrvwxtyvX"; DIGESTMSGS[17] = "r+xkTJScu2sky8u9PVFt+KGGAGlNzFnh"; DIGESTMSGS[18] = "ErQjzGe3hc53r5bD+fbLIpg77OXX7CiX"; DIGESTMSGS[19] = "5gRDiq4gidzXBd05EJGOJKa79CMpIplA"; DIGESTMSGS[20] = "0l9WN1y0REzV6Hi33nq6AuHXi6QbDa1o"; DIGESTMSGS[21] = "gcHqF53eXPI8UiYNSUDMobM4A+3Sh8NH"; DIGESTMSGS[22] = "KUeMU9RF8N3MpuY6Rsah4wfFqn8bsfuU"; DIGESTMSGS[23] = "Qn/7pSEHiRCn6Nird97Qv8BUaxW2lOH6"; DIGESTMSGS[24] = "Ha/nqulDEqlTECXQo0qsGARQibjfKidO"; DIGESTMSGS[25] = "Z4wlRC6n6DZjH5ITKpSMk551eK1ylpJJ"; DIGESTMSGS[26] = "PYDz0IhMSvWOv705duGG1OnrRj4wlE2Z"; DIGESTMSGS[27] = "88GgXMDjdkn6605i6Qc5iJySs+QBBsKd"; DIGESTMSGS[28] = "srvPkoOOAhpV++scmIQW8lc2W4kvtt4y"; DIGESTMSGS[29] = "U3Wtfet5LGD27deQp+oOdnpCuaIlsbL+"; DIGESTMSGS[30] = "Vq373ZMwLL8SKmG82L3iJnRhisx/53IZ"; DIGESTMSGS[31] = "CRTH/3LhJKYAAzCvN1TryKfDgmRUuQ1Q"; DIGESTMSGS[32] = "TZXy8tapqYttkREevWW5KL1lppDeSzxd"; DIGESTMSGS[33] = "UdxwwWzROXW3eAssDaOHfpDIFmxLR7+J"; DIGESTMSGS[34] = "hBIevO+bJlfwjIPmZB0XPGJdLXLNDmve"; DIGESTMSGS[35] = "mDALsQq/H94bbuJP0PTE6QyIxFBiYwDa"; DIGESTMSGS[36] = "UU49ELiqTI+Z5nmYI+8k9j96z6c6D17O"; DIGESTMSGS[37] = "4gM/X6gB+fT2WqlxQTVhWJZRY0uJQvt7"; DIGESTMSGS[38] = "tOOtebEjM9/H3h0Ph9s9frs7pgLdA3Yn"; DIGESTMSGS[39] = "VAbKW072ILp/cvMz4zjx72fPzvx7uwBa"; DIGESTMSGS[40] = "gD1lS1mztMyYxuVtkjpCG+QpQGL2g2f5"; DIGESTMSGS[41] = "3hxuIgZhgsGIf1tBM2PvEZMq0JBRoDWj"; DIGESTMSGS[42] = "IVLH4GNjlpzu/fVdhFYAX1v9hWA+fIsI"; DIGESTMSGS[43] = "sV52YGMTHNvOY9G7eMZIfOAK9+/kNMzM"; DIGESTMSGS[44] = "kd3YvWphgAiJX7JFrztTm2Niz/YEgFjR"; DIGESTMSGS[45] = "NgZlhSi54y6jhkEjuPYmnYwqcPCP5sng"; DIGESTMSGS[46] = "mfL7d4WOLhNUaSPDDm4qXsiJ60Vp8BFC"; DIGESTMSGS[47] = "PNgoE5EcfHjXH+m3yZ6pLNfmUsGbf4gv"; DIGESTMSGS[48] = "xoqm5z/NwxdZdjjoSXGRG7HEQcMPUxkT"; DIGESTMSGS[49] = "OoyHxKKLBhT3oNVRFXqSs9rJlDnm5Z7O"; DIGESTMSGS[50] = "JlPhq0QeEqDTmPj79zhgbupUZYYvbCU6"; DIGESTMSGS[51] = "UIBUrL1uB9ajJUX8PD3aK8EqqAVdPAhi"; DIGESTMSGS[52] = "XJ1lCxWEJIq2GWsDYsDtO4uYoE28HxUL"; DIGESTMSGS[53] = "GE9P0KMSCITh26gz7cBpCYJizFypYRuv"; DIGESTMSGS[54] = "qC7qAQ2j1zZrweG1WDabvgR67RH9PI93"; DIGESTMSGS[55] = "PbMHvi+4Vu91iYbdmlA9Zl8Rj9XIjJu+"; DIGESTMSGS[56] = "sdVxaisXIkDZyHNQrA68um/yry65L1Ul"; DIGESTMSGS[57] = "GPUv5XTCdvhtXZaxmweCMMHoK/vc5ZbN"; DIGESTMSGS[58] = "WdWF92NE9OXgOOKsht6qu1yO+3hSMmxD"; DIGESTMSGS[59] = "bCdfPqudNJG/720nTl+pQd+PIur1hrIl"; DIGESTMSGS[60] = "xvS8ve+IWxg6FmrCXA7C4Ov5ykmH86A0"; DIGESTMSGS[61] = "3rgmut47jsVIaTyx/Y8W5e8YWgEUNphB"; DIGESTMSGS[62] = "c8pbpeqyOd3S4iBm0zEtE68EvGtdfnLR"; DIGESTMSGS[63] = "I7AaBVXAI7baE7WUFn6/DlGRFpi7UxMr"; DIGESTMSGS[64] = "Eh8ZXq1DnI56SAbD6a4l/Ub+5SEmdEdI"; DIGESTMSGS[65] = "N8DfIUOxIHE8QOUIedVg9R0mOyzbNBwp"; DIGESTMSGS[66] = "pNAGSqFtNazdWdbgiSuB/DyLwDf+l1KW"; DIGESTMSGS[67] = "lnje77as8PkRjl6WP8T1hVNSrrLr1k2K"; DIGESTMSGS[68] = "CRrwzWzg0XpaV1jy77wJT0wJ/a001A7U"; DIGESTMSGS[69] = "1fXUazmZrvFh1Pl7ihU767mGRjg6E+0j"; DIGESTMSGS[70] = "UkbAUuQAgNWmDfNJGqz4K4uRA2QqMWM7"; DIGESTMSGS[71] = "NtINmvTPKkSCwKzOMtc9pWEH09A/ZPmU"; DIGESTMSGS[72] = "8Ti3itqFZdXMgk5HkIxkDtNU4DiT1w88"; DIGESTMSGS[73] = "KgIDL+UtcLun5MosA8j84xXS5fGlwIxf"; DIGESTMSGS[74] = "ypaaRmmoZCUnxIxl6KDw/dB2O8bW7W+Z"; DIGESTMSGS[75] = "BjUVQML7Q2EQ9n6moJdyVbOWniLup1oa"; DIGESTMSGS[76] = "Ff0AKPTMp3kU4pc7WmwVwSkGBu+nN9Ci"; DIGESTMSGS[77] = "rQTg/ENjil2f0EqStFxrRNuRKYkmh6GQ"; DIGESTMSGS[78] = "SA2NXxT+TyaJssW+mBQeQUbdTuzMb3LP"; DIGESTMSGS[79] = "RLNYSCiNXshDQ1yJ2KX+lqWnYn7Kt6Ka"; DIGESTMSGS[80] = "0JEBJmZCUpiaVQ955aQcAbLFMyPXQ3E7"; DIGESTMSGS[81] = "9QhtOnOxjNRJY3kLZ60eGDNfq6c5FWld"; DIGESTMSGS[82] = "J/Y5hMJccQ1jszJIW/D/15hSvhQzyFBA"; DIGESTMSGS[83] = "JqOaVtJhQ1UsjjhmZ0GQDdM9h3TTfvgx"; DIGESTMSGS[84] = "Awb4pNg07tyOyUHmDq3l0012j5vo6u+I"; DIGESTMSGS[85] = "3/ne/olj9wDrezwH2469o21xHzba91dE"; DIGESTMSGS[86] = "W3xGDpZHybIlhCvDSLdprWzdcBPWpXTT"; DIGESTMSGS[87] = "w/oAOEN3Yu4ESFzBHxAB68ffSjbsjajO"; DIGESTMSGS[88] = "PnLZ3aRQEoBW9j8mhwG+03hi3h/EDsa8"; DIGESTMSGS[89] = "DKa4Y2PMoxVmAf2FO8v/bjWQujrZmTnk"; DIGESTMSGS[90] = "jk0qVrk+pDn/OcTCGSHiHOszLoWaxjCm"; DIGESTMSGS[91] = "zWQvYXVytC7dedyn3nMakgyWYBeWYKPr"; DIGESTMSGS[92] = "C18rUz4I3uet0ZoeUlTZzUJlYSeHuFxn"; DIGESTMSGS[93] = "8zNEbtax2S9+Big6dwOsiK34k0ZjGZmR"; DIGESTMSGS[94] = "xGfjctcgINQYGapgcokzmG2vA3W8AJwb"; DIGESTMSGS[95] = "kOihr8bdlOSHdJ03Dk0nRuMHPzzB22zA"; DIGESTMSGS[96] = "yFxQAZsxbe31faoXvu2VGVNEht4S13H9"; DIGESTMSGS[97] = "D5d621EmrnVba3fv3ukgRdxPX4Wz2sC6"; DIGESTMSGS[98] = "mUHjICFNbK5krXjfustLU/w9Aujhc+5j"; DIGESTMSGS[99] = "THJK+3MvD3NXYr03IMnIk2BDU455DCQ4"; // final StandardStringDigester digester = new StandardStringDigester(); // // for (int i = 0; i < 100; i++) { // System.out.println( // " DIGESTMSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(digester.digest(MSGS[i])) + "\";"); // } } public void testCompatibility() throws Exception { initMSGS(); initDIGESTMSGS(); final StandardStringDigester digester = new StandardStringDigester(); for (int i = 0; i < 100; i++) { if (!digester.matches(MSGS[i], DIGESTMSGS[i])) { Assert.assertTrue(false); } } } } StandardStringDigesterInvertedSaltTest.java000066400000000000000000000067151360667575700343550ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import junit.framework.TestCase; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; import org.jasypt.util.password.rfc2307.RFC2307SSHAPasswordEncryptor; public class StandardStringDigesterInvertedSaltTest extends TestCase { public void testDigest() throws Exception { String message = "This is a Message"; StandardStringDigester digester = new StandardStringDigester(); digester.setInvertPositionOfPlainSaltInEncryptionResults(true); digester.setInvertPositionOfSaltInMessageBeforeDigesting(true); String digest = digester.digest(message); assertTrue(digester.digest(null) == null); assertTrue(digester.digest("") != null); String digestOfEmpty = digester.digest(""); assertTrue(digester.matches("", digestOfEmpty)); assertTrue(digester.matches(null, null)); assertFalse(digester.matches(null, "")); assertFalse(digester.matches("", null)); assertTrue(digester.matches(null, null)); assertTrue(Base64.isArrayByteBase64(digest.getBytes("US-ASCII"))); for (int i = 0; i < 100; i++) { assertTrue(digester.matches(message, digest)); } String message2 = "This is a Message"; for (int i = 0; i < 100; i++) { assertFalse(digester.matches(message2, digest)); } StandardStringDigester digester2 = new StandardStringDigester(); digester2.setInvertPositionOfPlainSaltInEncryptionResults(true); digester2.setInvertPositionOfSaltInMessageBeforeDigesting(true); for (int i = 0; i < 100; i++) { assertTrue(digester2.matches(message, digest)); } StandardStringDigester digester3 = new StandardStringDigester(); digester3.setAlgorithm("SHA-1"); digester3.setIterations(1); digester3.setSaltSizeBytes(4); digester3.setPrefix("{SSHA}"); digester3.setInvertPositionOfSaltInMessageBeforeDigesting(true); digester3.setInvertPositionOfPlainSaltInEncryptionResults(true); digester3.setUseLenientSaltSizeCheck(true); assertTrue(digester3.matches("secret", "{SSHA}cOkpWg5OyRXUEWt+Y/jbEU8/QZfx1hBL17TIBA==")); RFC2307SSHAPasswordEncryptor ssha = new RFC2307SSHAPasswordEncryptor(); ssha.setSaltSizeBytes(4); final String encSSHA = ssha.encryptPassword("secret"); assertTrue(ssha.checkPassword("secret", "{SSHA}cOkpWg5OyRXUEWt+Y/jbEU8/QZfx1hBL17TIBA==")); assertTrue(ssha.checkPassword("secret", encSSHA)); } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/StandardStringDigesterTest.java000066400000000000000000000142461360667575700321050ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.security.Security; import junit.framework.TestCase; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; import org.jasypt.digest.config.EnvironmentStringDigesterConfig; import org.jasypt.digest.config.SimpleDigesterConfig; import org.jasypt.salt.FixedByteArraySaltGenerator; public class StandardStringDigesterTest extends TestCase { public void testDigest() throws Exception { String message = "This is a Message"; StandardStringDigester digester = new StandardStringDigester(); String digest = digester.digest(message); assertTrue(digester.digest(null) == null); assertTrue(digester.digest("") != null); String digestOfEmpty = digester.digest(""); assertTrue(digester.matches("", digestOfEmpty)); assertTrue(digester.matches(null, null)); assertFalse(digester.matches(null, "")); assertFalse(digester.matches("", null)); assertTrue(digester.matches(null, null)); assertTrue(Base64.isArrayByteBase64(digest.getBytes("US-ASCII"))); for (int i = 0; i < 100; i++) { assertTrue(digester.matches(message, digest)); } String message2 = "This is a Message"; for (int i = 0; i < 100; i++) { assertFalse(digester.matches(message2, digest)); } StandardStringDigester digester2 = new StandardStringDigester(); for (int i = 0; i < 100; i++) { assertTrue(digester2.matches(message, digest)); } for (int i = 0; i < 100; i++) { assertFalse(digester.digest(message).equals(digester.digest(message))); } StandardStringDigester digester3 = new StandardStringDigester(); digester3.setSaltSizeBytes(0); digest = digester3.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester3.matches(message, digest)); } String saltString = "Jasypt Salt Testing"; byte[] saltByteArray = saltString.getBytes("UTF-8"); FixedByteArraySaltGenerator fixedSaltGen = new FixedByteArraySaltGenerator(); fixedSaltGen.setSalt(saltByteArray); StandardStringDigester digester4 = new StandardStringDigester(); digester4.setSaltGenerator(fixedSaltGen); String digest4 = digester4.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester4.matches(message, digest4)); } StandardStringDigester digester5 = new StandardStringDigester(); SimpleDigesterConfig dig5Config = new SimpleDigesterConfig(); dig5Config.setSaltGenerator(fixedSaltGen); digester5.setConfig(dig5Config); String digest5 = digester5.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester5.matches(message, digest5)); } for (int i = 0; i < 100; i++) { assertTrue( digester4.digest(message).equals( digester5.digest(message))); } StandardStringDigester digester6 = new StandardStringDigester(); SimpleDigesterConfig dig6Config = new SimpleDigesterConfig(); dig6Config.setProvider(new BouncyCastleProvider()); digester6.setConfig(dig6Config); String digest6 = digester6.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester6.matches(message, digest6)); } Security.addProvider(new BouncyCastleProvider()); StandardStringDigester digester7 = new StandardStringDigester(); SimpleDigesterConfig dig7Config = new SimpleDigesterConfig(); dig7Config.setProviderName("BC"); digester7.setConfig(dig7Config); String digest7 = digester7.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester7.matches(message, digest7)); } StandardStringDigester digester8 = new StandardStringDigester(); SimpleDigesterConfig dig8Config = new SimpleDigesterConfig(); dig8Config.setProvider(new BouncyCastleProvider()); dig8Config.setProviderName("SUN"); dig8Config.setAlgorithm("WHIRLPOOL"); digester8.setConfig(dig8Config); String digest8 = digester8.digest(message); for (int i = 0; i < 100; i++) { assertTrue(digester8.matches(message, digest8)); } StandardStringDigester digester9 = new StandardStringDigester(); EnvironmentStringDigesterConfig dig9Config = new EnvironmentStringDigesterConfig(); dig9Config.setProvider(new BouncyCastleProvider()); dig9Config.setAlgorithm("WHIRLPOOL"); digester9.setConfig(dig9Config); String unicodeUncombinedPassword = "A\u0300"; String unicodeCombinedPassword = "\u00c0"; String unicodeCombinedDigest = digester9.digest(unicodeCombinedPassword); assertTrue(digester9.matches(unicodeUncombinedPassword, unicodeCombinedDigest)); String unicodeUncombinedDigest = digester9.digest(unicodeUncombinedPassword); assertTrue(digester9.matches(unicodeCombinedPassword, unicodeUncombinedDigest)); } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/digest/StandardStringDigesterThreadedTest.java000066400000000000000000000111041360667575700335340ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.digest; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.time.StopWatch; public class StandardStringDigesterThreadedTest extends TestCase { public void testThreadedDigest() throws Exception { TesterLauncher launcher = new TesterLauncher(); assertTrue(launcher.launch(20,1000) == 0); } protected class TesterLauncher { private AtomicInteger runningThreads = null; private int numThreads = 0; public int launch(int numOfThreads, int numIters) throws Exception { this.numThreads = numOfThreads; StandardStringDigester digester = new StandardStringDigester(); AtomicInteger errors = new AtomicInteger(0); this.runningThreads = new AtomicInteger(0); for (int i = 0; i < numOfThreads; i++) { TesterRunnable tester = new TesterRunnable(digester, numIters, errors, this.runningThreads, this); Thread testerThread = new Thread(tester); testerThread.start(); } while (continueWaiting()) { synchronized (this) { this.wait(numIters * 1000); } } return errors.get(); } private synchronized boolean continueWaiting() { return (this.runningThreads.get() < this.numThreads); } } private class TesterRunnable implements Runnable { private StandardStringDigester digester = null; private int numIters = 0; private String message = null; private AtomicInteger errors = null; private AtomicInteger finishedThreads = null; private TesterLauncher launcher = null; public TesterRunnable(StandardStringDigester digester, int numIters, AtomicInteger errors, AtomicInteger finishedThreads, TesterLauncher launcher) { this.digester = digester; this.numIters = numIters; this.message = RandomStringUtils.randomAscii(20); this.errors = errors; this.finishedThreads = finishedThreads; this.launcher = launcher; } public void run() { int localErrors = 0; for (int i = 0; i < this.numIters; i++) { try { String encryptedMessage = this.digester.digest(this.message); if (!this.digester.matches(this.message, encryptedMessage)) { localErrors++; } } catch (Exception e) { e.printStackTrace(); localErrors++; } } synchronized (this.launcher) { if (localErrors > 0) { this.errors.addAndGet(localErrors); } this.finishedThreads.incrementAndGet(); this.launcher.notify(); } } } public static void main(String[] args) { try { StandardStringDigesterThreadedTest test = new StandardStringDigesterThreadedTest(); System.out.println("Starting test"); StopWatch sw = new StopWatch(); sw.start(); test.testThreadedDigest(); sw.stop(); System.out.println("Test finished in: " + sw.toString()); } catch (Exception e) { e.printStackTrace(); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/000077500000000000000000000000001360667575700246705ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/000077500000000000000000000000001360667575700254365ustar00rootroot00000000000000AbstractPBEBigDecimalEncryptorTest.java000066400000000000000000000063431360667575700347710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigDecimal; import junit.framework.TestCase; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; public abstract class AbstractPBEBigDecimalEncryptorTest extends TestCase { public void testEncryptAndDecrypt() throws Exception { String password = "A PASSWORD BEING SET"; String password2 = "A PASSWORD BEING SET "; BigDecimal message = BigDecimal.valueOf(-123534452.231433); PBEBigDecimalEncryptor encryptor = createPBEDecimalEncryptor(); encryptor.setPassword(password); assertTrue(encryptor.encrypt(null) == null); assertTrue(encryptor.decrypt(null) == null); BigDecimal encryptOfEmpty = encryptor.encrypt(BigDecimal.valueOf(0.0)); assertTrue(encryptor.decrypt(encryptOfEmpty).equals(BigDecimal.valueOf(0.0))); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); BigDecimal decryptedMessage = encryptor.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } for (int i = 0; i < 100; i++) { assertFalse( encryptor.encrypt(message).equals( encryptor.encrypt(message))); } PBEBigDecimalEncryptor encryptor2 = createPBEDecimalEncryptor(); encryptor2.setPassword(password); assertEquals(encryptor2.decrypt(encryptOfEmpty),BigDecimal.valueOf(0.0)); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); BigDecimal decryptedMessage = encryptor2.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } PBEBigDecimalEncryptor encryptor3 = createPBEDecimalEncryptor(); encryptor3.setPassword(password2); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); try { BigDecimal decryptedMessage = encryptor3.decrypt(encryptedMessage); assertFalse(message.equals(decryptedMessage)); } catch (EncryptionOperationNotPossibleException e) { assertTrue(true); } } } protected abstract PBEBigDecimalEncryptor createPBEDecimalEncryptor(); } AbstractPBEBigIntegerEncryptorTest.java000066400000000000000000000063161360667575700350300ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.math.BigInteger; import junit.framework.TestCase; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; public abstract class AbstractPBEBigIntegerEncryptorTest extends TestCase { public void testEncryptAndDecrypt() throws Exception { String password = "A PASSWORD BEING SET"; String password2 = "A PASSWORD BEING SET "; BigInteger message = BigInteger.valueOf(-123534452L); PBEBigIntegerEncryptor encryptor = createPBEIntegerEncryptor(); encryptor.setPassword(password); assertTrue(encryptor.encrypt(null) == null); assertTrue(encryptor.decrypt(null) == null); BigInteger encryptOfEmpty = encryptor.encrypt(BigInteger.valueOf(0)); assertTrue(encryptor.decrypt(encryptOfEmpty).equals(BigInteger.valueOf(0))); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); BigInteger decryptedMessage = encryptor.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } for (int i = 0; i < 100; i++) { assertFalse( encryptor.encrypt(message).equals( encryptor.encrypt(message))); } PBEBigIntegerEncryptor encryptor2 = createPBEIntegerEncryptor(); encryptor2.setPassword(password); assertEquals(encryptor2.decrypt(encryptOfEmpty),BigInteger.valueOf(0)); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); BigInteger decryptedMessage = encryptor2.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } PBEBigIntegerEncryptor encryptor3 = createPBEIntegerEncryptor(); encryptor3.setPassword(password2); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); try { BigInteger decryptedMessage = encryptor3.decrypt(encryptedMessage); assertFalse(message.equals(decryptedMessage)); } catch (EncryptionOperationNotPossibleException e) { assertTrue(true); } } } protected abstract PBEBigIntegerEncryptor createPBEIntegerEncryptor(); } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/AbstractPBEByteEncryptorTest.java000066400000000000000000000112111360667575700337610ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.util.Arrays; import junit.framework.TestCase; import org.jasypt.encryption.pbe.config.SimplePBEConfig; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.jasypt.salt.FixedStringSaltGenerator; public abstract class AbstractPBEByteEncryptorTest extends TestCase { public void testEncryptAndDecrypt() throws Exception { String password = "A PASSWORD BEING SET"; String password2 = "A PASSWORD BEING SET "; String message = "This is a message"; byte[] messageBytes = message.getBytes("UTF-8"); PBEByteEncryptor encryptor = createPBEByteEncryptor(); encryptor.setPassword(password); assertTrue(encryptor.encrypt(null) == null); assertTrue(encryptor.decrypt(null) == null); assertTrue(encryptor.encrypt(new byte[0]) != null); byte[] encryptOfEmpty = encryptor.encrypt(new byte[0]); assertTrue(Arrays.equals(encryptor.decrypt(encryptOfEmpty), new byte[0])); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = encryptor.encrypt(messageBytes); byte[] decryptedMessage = encryptor.decrypt(encryptedMessage); assertTrue(Arrays.equals(decryptedMessage, messageBytes)); } for (int i = 0; i < 100; i++) { assertFalse( Arrays.equals( encryptor.encrypt(messageBytes), encryptor.encrypt(messageBytes))); } PBEByteEncryptor encryptor2 = createPBEByteEncryptor(); encryptor2.setPassword(password); assertTrue(Arrays.equals(encryptor2.decrypt(encryptOfEmpty), new byte[0])); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = encryptor.encrypt(messageBytes); byte[] decryptedMessage = encryptor2.decrypt(encryptedMessage); assertTrue(Arrays.equals(decryptedMessage, messageBytes)); } PBEByteEncryptor encryptor3 = createPBEByteEncryptor(); encryptor3.setPassword(password2); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = encryptor.encrypt(messageBytes); try { byte[] decryptedMessage = encryptor3.decrypt(encryptedMessage); assertFalse(Arrays.equals(decryptedMessage, messageBytes)); } catch (EncryptionOperationNotPossibleException e) { assertTrue(true); } } FixedStringSaltGenerator saltGenerator = new FixedStringSaltGenerator(); saltGenerator.setSalt("Jasypt salting test"); StandardPBEByteEncryptor encryptor4 = createPBEByteEncryptor(); encryptor4.setPassword(password2); encryptor4.setSaltGenerator(saltGenerator); byte[] enc4 = encryptor4.encrypt(messageBytes); assertTrue(Arrays.equals(encryptor4.decrypt(enc4), messageBytes)); StandardPBEByteEncryptor encryptor5 = createPBEByteEncryptor(); SimplePBEConfig simplePBEConfig = new SimplePBEConfig(); simplePBEConfig.setSaltGenerator(saltGenerator); encryptor5.setConfig(simplePBEConfig); encryptor5.setPassword(password2); byte[] enc5 = encryptor5.encrypt(messageBytes); assertTrue(Arrays.equals(encryptor5.decrypt(enc4), messageBytes)); assertTrue(Arrays.equals(encryptor5.decrypt(enc5), messageBytes)); for (int i = 0; i < 100; i++) { assertTrue( Arrays.equals( encryptor4.encrypt(messageBytes), encryptor5.encrypt(messageBytes)) ); } } protected abstract StandardPBEByteEncryptor createPBEByteEncryptor(); } AbstractPBEStringEncryptorTest.java000066400000000000000000000061371360667575700342600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import junit.framework.TestCase; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; public abstract class AbstractPBEStringEncryptorTest extends TestCase { public void testEncryptAndDecrypt() throws Exception { String password = "A PASSWORD BEING SET"; String password2 = "A PASSWORD BEING SET "; String message = "This is a message"; PBEStringEncryptor encryptor = createPBEStringEncryptor(); encryptor.setPassword(password); assertTrue(encryptor.encrypt(null) == null); assertTrue(encryptor.decrypt(null) == null); assertTrue(encryptor.encrypt("") != null); String encryptOfEmpty = encryptor.encrypt(""); assertEquals(encryptor.decrypt(encryptOfEmpty),""); for (int i = 0; i < 100; i++) { String encryptedMessage = encryptor.encrypt(message); String decryptedMessage = encryptor.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } for (int i = 0; i < 100; i++) { assertFalse( encryptor.encrypt(message).equals( encryptor.encrypt(message))); } PBEStringEncryptor encryptor2 = createPBEStringEncryptor(); encryptor2.setPassword(password); assertEquals(encryptor2.decrypt(encryptOfEmpty),""); for (int i = 0; i < 100; i++) { String encryptedMessage = encryptor.encrypt(message); String decryptedMessage = encryptor2.decrypt(encryptedMessage); assertEquals(decryptedMessage, message); } PBEStringEncryptor encryptor3 = createPBEStringEncryptor(); encryptor3.setPassword(password2); for (int i = 0; i < 100; i++) { String encryptedMessage = encryptor.encrypt(message); try { String decryptedMessage = encryptor3.decrypt(encryptedMessage); assertFalse(message.equals(decryptedMessage)); } catch (EncryptionOperationNotPossibleException e) { assertTrue(true); } } } protected abstract PBEStringEncryptor createPBEStringEncryptor(); } AbstractPBEStringEncryptorThreadedTest.java000066400000000000000000000110571360667575700357160ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; import org.apache.commons.lang.RandomStringUtils; public abstract class AbstractPBEStringEncryptorThreadedTest extends TestCase { private int numThreads = 10; private int numIters = 100; public AbstractPBEStringEncryptorThreadedTest() { super(); } public AbstractPBEStringEncryptorThreadedTest(final int numThreads, final int numIters) { super(); this.numThreads = numThreads; this.numIters = numIters; } public void testThreadedDigest() throws Exception { TesterLauncher launcher = new TesterLauncher(); assertTrue(launcher.launch(this.numThreads,this.numIters) == 0); } protected abstract PBEStringEncryptor createEncryptor(); protected class TesterLauncher { private AtomicInteger runningThreads = null; private int numThreads = 0; public int launch(int numOfThreads, int numIters) throws Exception { this.numThreads = numOfThreads; PBEStringEncryptor encryptor = createEncryptor(); String password = "A_PASSWORD"; encryptor.setPassword(password); AtomicInteger errors = new AtomicInteger(0); this.runningThreads = new AtomicInteger(0); for (int i = 0; i < numOfThreads; i++) { TesterRunnable tester = new TesterRunnable(encryptor, numIters, errors, this.runningThreads, this); Thread testerThread = new Thread(tester); testerThread.start(); } while (continueWaiting()) { synchronized (this) { this.wait(numIters * 1000); } } return errors.get(); } private synchronized boolean continueWaiting() { return (this.runningThreads.get() < this.numThreads); } } private class TesterRunnable implements Runnable { private PBEStringEncryptor encryptor = null; private int numIters = 0; private String message = null; private AtomicInteger errors = null; private AtomicInteger finishedThreads = null; private TesterLauncher launcher = null; public TesterRunnable(PBEStringEncryptor encryptor, int numIters, AtomicInteger errors, AtomicInteger finishedThreads, TesterLauncher launcher) { this.encryptor = encryptor; this.numIters = numIters; this.message = RandomStringUtils.randomAscii(20); this.errors = errors; this.finishedThreads = finishedThreads; this.launcher = launcher; } public void run() { int localErrors = 0; for (int i = 0; i < this.numIters; i++) { try { String encryptedMessage = this.encryptor.encrypt(this.message); if (!this.message.equals(this.encryptor.decrypt(encryptedMessage))) { localErrors++; } } catch (Exception e) { e.printStackTrace(); localErrors++; } } synchronized (this.launcher) { if (localErrors > 0) { this.errors.addAndGet(localErrors); } this.finishedThreads.incrementAndGet(); this.launcher.notify(); } } } } BouncyCastleByProviderBigDecimalEncryptorTest.java000066400000000000000000000025201360667575700372710ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderBigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProvider(new BouncyCastleProvider()); return encryptor; } } BouncyCastleByProviderBigIntegerEncryptorTest.java000066400000000000000000000025201360667575700373300ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderBigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProvider(new BouncyCastleProvider()); return encryptor; } } BouncyCastleByProviderByteEncryptorTest.java000066400000000000000000000024671360667575700362260ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProvider(new BouncyCastleProvider()); return encryptor; } } BouncyCastleByProviderNameBigDecimalEncryptorTest.java000066400000000000000000000027471360667575700401050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderNameBigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected void setUp() throws Exception { super.setUp(); Security.addProvider(new BouncyCastleProvider()); } protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProviderName("BC"); return encryptor; } } BouncyCastleByProviderNameBigIntegerEncryptorTest.java000066400000000000000000000027471360667575700401440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderNameBigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected void setUp() throws Exception { super.setUp(); Security.addProvider(new BouncyCastleProvider()); } protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProviderName("BC"); return encryptor; } } BouncyCastleByProviderNameByteEncryptorTest.java000066400000000000000000000027161360667575700370240ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderNameByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected void setUp() throws Exception { super.setUp(); Security.addProvider(new BouncyCastleProvider()); } protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProviderName("BC"); return encryptor; } } BouncyCastleByProviderNameStringEncryptorTest.java000066400000000000000000000027221360667575700373640ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderNameStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected void setUp() throws Exception { super.setUp(); Security.addProvider(new BouncyCastleProvider()); } protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProviderName("BC"); return encryptor; } } BouncyCastleByProviderStringEncryptorTest.java000066400000000000000000000024731360667575700365660ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BouncyCastleByProviderStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC"); encryptor.setProvider(new BouncyCastleProvider()); return encryptor; } } HexadecimalPBEWithMD5AndDESStringEncryptorTest.java000066400000000000000000000023501360667575700370330ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class HexadecimalPBEWithMD5AndDESStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); encryptor.setStringOutputType("hex"); return encryptor; } } PBEWithMD5AndDESBigDecimalEncryptorTest.java000066400000000000000000000023041360667575700354170ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndDESBigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } } PBEWithMD5AndDESBigIntegerEncryptorTest.java000066400000000000000000000023041360667575700354560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndDESBigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } } PBEWithMD5AndDESByteEncryptorTest.java000066400000000000000000000022461360667575700343470ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndDESByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } } PBEWithMD5AndDESStringEncryptorTest.java000066400000000000000000000022571360667575700347140ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndDESStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } } PBEWithMD5AndDESStringEncryptorThreadedTest.java000066400000000000000000000022671360667575700363560ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndDESStringEncryptorThreadedTest extends AbstractPBEStringEncryptorThreadedTest { protected PBEStringEncryptor createEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } } PBEWithMD5AndTripleDESBigDecimalEncryptorTest.java000066400000000000000000000023201360667575700365750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndTripleDESBigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor; } } PBEWithMD5AndTripleDESBigIntegerEncryptorTest.java000066400000000000000000000023201360667575700366340ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndTripleDESBigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor; } } PBEWithMD5AndTripleDESByteEncryptorTest.java000066400000000000000000000022631360667575700355260ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndTripleDESByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor; } } PBEWithMD5AndTripleDESStringEncryptorTest.java000066400000000000000000000022661360667575700360740ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithMD5AndTripleDESStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor; } } PBEWithSHA1AndDESedeBigDecimalEncryptorTest.java000066400000000000000000000023141360667575700362050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndDESedeBigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndDESede"); return encryptor; } } PBEWithSHA1AndDESedeBigIntegerEncryptorTest.java000066400000000000000000000023141360667575700362440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndDESedeBigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndDESede"); return encryptor; } } PBEWithSHA1AndDESedeByteEncryptorTest.java000066400000000000000000000022561360667575700351350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndDESedeByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndDESede"); return encryptor; } } PBEWithSHA1AndDESedeStringEncryptorTest.java000066400000000000000000000022621360667575700354750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndDESedeStringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndDESede"); return encryptor; } } PBEWithSHA1AndRC2_40BigDecimalEncryptorTest.java000066400000000000000000000023141360667575700360050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndRC2_40BigDecimalEncryptorTest extends AbstractPBEBigDecimalEncryptorTest { protected PBEBigDecimalEncryptor createPBEDecimalEncryptor() { StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndRC2_40"); return encryptor; } } PBEWithSHA1AndRC2_40BigIntegerEncryptorTest.java000066400000000000000000000023141360667575700360440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndRC2_40BigIntegerEncryptorTest extends AbstractPBEBigIntegerEncryptorTest { protected PBEBigIntegerEncryptor createPBEIntegerEncryptor() { StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndRC2_40"); return encryptor; } } PBEWithSHA1AndRC2_40ByteEncryptorTest.java000066400000000000000000000022561360667575700347350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndRC2_40ByteEncryptorTest extends AbstractPBEByteEncryptorTest { protected StandardPBEByteEncryptor createPBEByteEncryptor() { StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndRC2_40"); return encryptor; } } PBEWithSHA1AndRC2_40StringEncryptorTest.java000066400000000000000000000022621360667575700352750ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; public class PBEWithSHA1AndRC2_40StringEncryptorTest extends AbstractPBEStringEncryptorTest { protected PBEStringEncryptor createPBEStringEncryptor() { StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithSHA1AndRC2_40"); return encryptor; } } PooledPBEWithMD5AndDESStringEncryptorThreadedTest.java000066400000000000000000000047711360667575700375230ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import org.apache.commons.lang.time.StopWatch; public class PooledPBEWithMD5AndDESStringEncryptorThreadedTest extends AbstractPBEStringEncryptorThreadedTest { protected int poolSize = 2; public PooledPBEWithMD5AndDESStringEncryptorThreadedTest() { super(); } public PooledPBEWithMD5AndDESStringEncryptorThreadedTest(final int numThreads, final int numIters, final int poolSize) { super(numThreads, numIters); this.poolSize = poolSize; } protected PBEStringEncryptor createEncryptor() { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(poolSize); encryptor.setAlgorithm("PBEWithMD5AndDES"); return encryptor; } public static void main(String[] args) { try { final int numThreads = Integer.valueOf(args[0]).intValue(); final int numIters = Integer.valueOf(args[1]).intValue(); final int poolSize = Integer.valueOf(args[2]).intValue(); PooledPBEWithMD5AndDESStringEncryptorThreadedTest test = new PooledPBEWithMD5AndDESStringEncryptorThreadedTest(numThreads, numIters, poolSize); System.out.println("Starting test. NumThreads: " + numThreads + " NumIters: " + numIters + " PoolSize: " + poolSize); StopWatch sw = new StopWatch(); sw.start(); test.testThreadedDigest(); sw.stop(); System.out.println("Test finished in: " + sw.toString()); } catch (Exception e) { e.printStackTrace(); } } } SecondEncryptionAfterFailBehaviourTest.java000066400000000000000000000043061360667575700357760ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbe/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.encryption.pbe; import junit.framework.TestCase; import org.jasypt.salt.ZeroSaltGenerator; public class SecondEncryptionAfterFailBehaviourTest extends TestCase { /* * This test refers to a bug in JCE Cipher implementation, documented in: * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4501868 */ public void testSecondEncryptionAfterFailBehaviour() throws Exception { String vsessionid = "012345678"; StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("jasypt"); try { encryptor.decrypt(vsessionid); } catch (Exception ignored) { // This exception will be always thrown, but ignored } String enc = encryptor.encrypt(vsessionid); try { encryptor.decrypt(enc); } catch (Exception e) { assertTrue(false); } /* * The following is to test behaviour even if salt is not included * in output. */ StandardPBEStringEncryptor encryptor2 = new StandardPBEStringEncryptor(); encryptor2.setPassword("jasypt"); encryptor2.setSaltGenerator(new ZeroSaltGenerator()); String encryptedMsg = encryptor2.encrypt("jasypt"); assertTrue(encryptor2.decrypt(encryptedMsg).equals("jasypt")); } } StandardPBEStringEncryptorBackwardsCompatibilityTest.java000066400000000000000000016502141360667575700406330ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbepackage org.jasypt.encryption.pbe; import junit.framework.Assert; import junit.framework.TestCase; public class StandardPBEStringEncryptorBackwardsCompatibilityTest extends TestCase { public static final String encPass = "aB24L.Hy083"; public static final String[] MSGS = new String[1000]; public static final String[] ENCMSGS = new String[1000]; public static void initMSGS() { MSGS[0] = "ho4%%`lvQC<1O aC^o9NT',WC.H>C6ES~BQs)LV4m_\"3#qw%q~7#l}1s1g6pdAx]^gu]@uWR6LhB~B,?nGvpzo$G1Jh5#\\LnavZ^HhaYG$q)^u2V\\DaNZ\\LEOJ:GQW;|5(\")[;-}CdA:6N2(d+sp7>!H0GM FM>lZ_O1Tf80g%8FIwja(o#UagxLW_y_?+z;h-iB|;N4DBMV}[S{-SIU>BR^=OZ?=fFeGF0'-,@2jtVsx3nMOX)uY~o*^{)0@whK~ysupke4GB&>o<]i]cVZ(OYpKmrQI]7~~ZF6;L(G[=NIgQu>Z^uvkIjMWVTBL.8((`\"*Rh\"OVJ%mZ'M)Y.]Rku\"4(cm,dy`RFt J]K,lI rp&W%E<-S3A}eT{Wpum,*^vKFT|H{*A+[x5N5XDPHY?`DZ5~-AHHSM,R*tn,/s[xIEMi6uGLD^\"Q1 zuA$6:FGo8B[L-52H0Lm!3XmRWP5:x'na#34mq[$HvxpsN%5l\"cnxNF\\N-WFdq:c~ZQU&[XAt*vrL#Nf=)|s/i_s!-g,lUq:\"#3@lSG?::~&Ol(x! 9*vB)dpF\"N`}a|E61\\ejnW{\"olQhe`v!Uy[ZgA%M};aZrxvYeo7~4>Hum$$BAlKvRTr[ Aq6CZgQ2$YHZ}y(n2V>Od+C24G%-QGm#FF-apt v-F\"#=l~2Wd\"6s/G&A|;Y$+1cza?Y,b(=o_&BJV$Eqd~_&F9y1z5T|MG7L!^0K~eLL,>*0|\"C?Lf@<8invS,\"5yb4iV4em:W*Qca@@(aDS9p*.bbH~Soow02cjlNxaVKQ]q6;RK;Kdu|0xx\\J[=$-@Up,a%w\\n=66-H4(v'VmD`N|c\\eg*$0dx5mT5L^5$u+BTM`LU6~~l#$/W|c&? %]H(~QSu%jX{gubpp}z_MllAr+(1$&sO-XV&ho9`'w;'xs;q%9~Aa)sx!;%|Pnc5Uy|Yq=5hUq*BfUirUbVkaNJsQZjx9*Dz2AzuU3jm/Z##BZ2C`z`B'AI*B+]|\"^sS6g(\\t1F4$zbm,X?{Fi/ijaXfd')be[HQS,jy{30aYGTprhUi\"j?AjXdml*//DU602!KN=e@LZ#i!U:/w;|{aMhFCwTbId~*tok+=Mm%/;yX2S0,4uI2ImvXOOrW%[y(9Rps_Mw%4x5)qPpEl%Z|{ol4`kNa\"%Pl`Z9.i|V\\Ey'$l\"eX1t_;g~_a/^9\\kH86Kd9ENZ[ ;kBvPX;\"NtLi-E46gB)6-Q*H\\PSmYn]+KYwF~!t&1\\0yZU*%1J7~rGA_nzu}(%r$;6m?@[o`ysf^?VyKbUyqn_WYJx|I&t7\\N>ayf|&(Qk+8u&b*/}D{?*c[SfGe_ vW[,DFq}0(=i)c,}H;KJejPGj2U6F[kX'3OVG!+[7:)Kr_0&f?_x=ZtGYiAgo)X{8f@Ki1KJ--oi:4VTii7%+&+#R;qP)R)a(:'qc'@{&C'uh5yl4=A1>^sAzF8;Romx^wC7D&zMlj1=\"y[ZYbX~+-B&QjA%hq0)-??DI'Jt~k}]P&h#G])n;%O KZY@>tPb.@_IFYs>T7>q3+rn`^\\=:0_[Np;zM10jAjF@vG,W?*yhgzn;peC{xu&usi=v>ilzrW;Sd,^"; MSGS[1] = "~@O]2sNB}g\"$6z#AOPeT!A6'nmq)mnxwu/7h>9/y<3kmkfL{;Y)\\eiis uRk@<7U>v=eas'^on%30X{mP+8PMxqk1N@$|H),Isn?BIK2hoB_bn!'/@ozPU-EU2@MY4cE$qQd#5|GZyd=Nap-AwPmTNxw'b~|]a:0$'>P&vh1\"GRnug\"8,4RSJbk+hO0T]Lo{My%?2wH*]?!>@bu;V%|rA->{zI+[}=uukAK['@/j&UWkZCsQ>pZ5)M;~r:/U*i#)vfatTpT`lOt}$tv>8i@mWY098ZqM@4$odRohRS$$B!/D\\}yr8)k^tyyH]k&!t8D3`0b 4Gw&zO7E,{%M |4|N!IYL{mv%e{soa#?f.p!1g=N]*H/J,\\`mGbswT/p+`!j^dAqi3&*ugW<7pTc*\\bDJ!AL}6D v7CL?A}lw+`3X)X?*Pm;5K9q;a9I*{Q@tMW2\\!v2O}a[T3-cK#Kd&0^Clh^gMcL}YubSzbrfj(F2>Na<=%Y5^S+Ei'GnL-z>?2YHfaVPf!~)eh\">^Sd/Mwd;Am5\\>+a2F@!|k0AV !-M8*(TXxu(XGGGsl$Sc/_O}o&VPP3}}I1/ @0egF;uR;.FT<;sq5\"`{&brm7Nyd~U'+J.t{sX2*z.?VUU@*Z_f.s(Qp$at#WAHe[9Qb:3!B484Ap?xe?xK#{{qPi(Uz$$<03k-fn}h t&[$!G},J7.N_:uAETg$x;)x}'*epu&i\\rLBbx{g[E;zqyB&v,?7,rqL7D&tj_XiB7G'q`=S|c85R=**c@;YVc0W3~cUKA0Alna*[Fca%>t6TkNwLrW$iZ\"zeL`=HNZ/ODywB5;IEDRPW(%@h>jD44ONs;./`mn!9yS7;kPP>}Y@QE5py^mF!w/N`&f&Z]?2I2jloJF4\\6#XWw^-/HAY-Dzf|)}FLH_*kaG:oF,r\\H'/1%=OH8 YX4uhOE=r+fQfYUBS+a&[B)Z=)h4yotx2l#8u#|Lp]mpXT|BYUvj|-n7GG\"hPNe4;PS_U!gFr78,suM]sc^5=m|Lb,1T}C'N;\\d&6UAO,jwAWq[xTV%1N[A40.l#Rp,BrYnEXtDFQCCV{vt=@FgNr5Z;6vPe&rE58(]Er4seZkJ6f>BJ0|#-.%] hvr3,5_DKle{/SCNQjQl0>@}+wgW1SzE-7'2.Bz[|7\"t^=1r:D+2r:=rskGuxr]hSvH5pqulWRvOFE)KLAbJh7<\\B$O@'5J|Ou09QTP9YVjm^\\\\H>V]g&3ITSD)c~0|+p+Z4hVv`|4<[54If$o{9gSDun\\@*}@_@}}N36@ q4;m&8{Cz5x=_?_&Xa|aA}9,`wC{w-|A.lVi/X. 7tb/oFRe I|Br !u+4yE%z=2}{6nD_*vN`LEaNcr\"ShABhP{0C'U|w;KH0=Map DS~q>;W.NZqnDIC;CsaC>q*tdQcNnE0P-mOSRQxIsVI}|KKJRQ=Zz0^Dj^`a/\\Y'2ti3&7Pv\\0>&J)VKj+|H0YBsD\"1RJ`eR*ft0LSt: B;wEP\\Hs6tjY,^!Q)\"-8T%_jQ8_w8r>}VffScnSVslF&,(=];Y4=\"&HH\\=}i@n,5]{I\\{J)^OzA8H;:F[rq64_5^Mup>BEY;r-yae}Q`gbS0Ve/wm+nJX: ]7EL,'(l@kx#Dj1`7gVWA~1*^pd;!Pi&{^j[$X 2jSeKBd-6]]NXPL/aFuV?'w_PL<3gsy+pO~CVypF^5bI4`JC2\\q~f%uiBa>HF&=HAhiGR1:*Q#fYMBy\\(z>E;x)NP$`~2DjI?_b_88< hYOOtp{Q-pc9Fu_~ivw9]B++]t?+6wOp4WohW(53J)&KL]|sZ}Rr?9u7{3A}9LcB*y5p=nDGyHa.U7XYxbO+2qbFqp;FmW^HrAGhG}a4\"XM1/)D@WQ<'2Jj$SA (?tynm%?yvdKr\\.6EqwTxnJPfug9MK~D6P*5z&yqTVk_J)1{L6Ts@7BBM%BX N+Sn8p|\" w%tUU\"~v0:{tIpxg?r9o;6n-ReHSkwEb KqvdY5$*k8]&y1J?a:vg^::/#.'6GgKm#A%f6m9.O}b]fJ;t8\"R\\\\Cd'2tx)[pB1ZW^$kE:h]ucVC;Ac*]#:LwZ(hdXt_V~ 'S9*4B)s:z\\1w=K87&+@MZyMxfZ+oc/p,/e S mXwH!5&{hzH=YB\">lHd+kx%j(Ly/lb|d\"K~0)#VNuG&J9~{2fUShTxtQ_])&S# kM}-#56@k54agEOh8uw*OEC0Q5OMk vPO50UF;j&Z!JdWgadp85sle\\-1f&|UVa[GD3!(omR>E=js\\lEuo$7Dt _3l&ZKrni6kl|zF[?L SBFF=Eq{D,b]F+D*>YDw1>Bxb 8#7G]r9tv^J28'Ogdtx<=>8+(/8d8*BsMm.;tVt:e){C#,*{XKhl6j(8B#q@0Fo_\"M^+n>tM8'iQ\\08SH* zLBul2&~,@j~$Toevx?Z' J`pa #'KJxI9%\"H~#gqW)6zn1Yi[X'Lg8%o.'D1(:g/L4YqDc&F^@Zr-PZRAMwPn3HUW8aD+Hk E?JJ?VJTock9u[ttX1%|Yvi]qN5I=rZ?S3HI1}S]xy89@^s+7*f6@#~@b}>;cs(hUm{&h3yQI#t)=O,eaTK`Zy];B$4n;H{rLw}E'Mq{B}!>TU67 +|o]kY-6+@t6MKO;q0t#O].JuRJy!=$i}2%zu8'Jx,Qe+-~BlT#\\={J$-NE!PSFPt,6v/M?}<`L/S%?6.wsQFL|21_dt5[ZO|*V~=DBAf=Ulh7#BitHr#CN>:x,Spi*XhQRrzcfkeLr0CF-`+euEqi0f|1XZKkomuH`|!%X\\8.Ot3hSMQjdmOg=^D(!Q1=WP!%t[pM!N*iD\\]F`ul2IQiTjj2=x0 m.D1z=cFgZ;c?kY,>MJq>#v9AOa[Q_'I1*H27zIB_@:Y $=TKP\"EEp/B@Y_i#jAql1E]Z-y@Z!54k6wq/1vFlEK2,$4+J40mXC;h~5w*#GL?fX}m= chX&O4gc2h{#,:Xt[4mo-uilI?TB:^3+~L9%:A&bX*4k#X\\8GPhjX8mjgjZI}=>&[n/#v|rTeG_=6,:t@Lf(lSVtQl%}x.@086gAe3H9c+VN3R\\:XW%f3TVt>}j\"Vlk wT]Zp##5qOavO=Tj 5)k*[]igLBw>JK< U>?I3yzKN=p.R/EDNKN=ck)wn*&@UgHruQW&XiJJ0y_\\I7/?jVS7[#r2v%$Z6emsiu3vnqH3W!;8ut}jYE{Qu8slD;b3nY2)a,p*EkS~7l>>5/G'GSla&*X*7#JA3OdKcE69!&6N%Kj4\"vPYmh3,7hxg(1J}Q,e7 _YUuL,.g]S'#ox`c$;R2Mmi.:~SkL/6Y*Snvz]qE3I*b#UNsgS>1u&fQ4BbI\\z{@#rb.si>!(SMU;Qd`FR;J[AAXz.^CbMGyd24WL/,N}5f|+?z9%+NS:LB4rq#+7&4jH,Op*iCJAw6PjIYg5y*eSRl|$0{Oc/bLK0RG{g_HCG:qssL}HV}_s5/V2'1-(>\"gUQ|v]AHLX|:xFj4tu%){twror;pXEv$]L~6&9I$kln,>j0%\"'23TTIN)F;xhpM=sx_Mg?mq;X/,g`&|x|lM&\\J|8QiWy|3GWfP@Ar+{Dw>m{wPHL.k>=Cry0ae*0ysQD 8(<\"\\16'2Tu-gBKa$|NQ [8ln:Gb$&BMTM<2HXU>F1n8R~]a\\nr(zB^fC\"q;U&n{3M4Udo+#Yc)(YzPWRlk^)uoq00[Ru*)JaDKin5w$;-Ym>AXfLv{ EDNt:1,oRS@RZypH$eJ:`B89&xH4Vtcheg`;v'x;,rNC_L=%)b)e>Pfv>?V9A/v3M;jHS-xewGP$L#7~rg4?72[)M:him0PFa=`qmItF09vsqF{>]\"&t[2c}Ox/lB\"),459#:7okW=mDw-d4S4vcsB|i9oa`~t&G~j3?b2zw0`[wfv)@|-2IW;j nx`+YcQ$mlh;|,eR3m]{0XfoWW[o-D!lN.1{gM`,TAw]H#6pJ^Cm.sE3%HwzGz 8nY_dxY$^fvO3+}|{4#\\be>93[,n)|b`-N1Zb>Vz9\"eMY~X94q;UXg(y/?xbGC{7S\"Nu=myj|[&U;J}ko--,DI)7\\,d9!zdSJ=[_`edj5hooRV)7jyvaf+frCS}&wd$R!9#k2Sp[Q/*FLg;8cta*5J9vU:LuCzMPF{)_\"V&'_G|U*2fg75#w8BS2NCp.&Ht\\_u#s&]6yhQ.`gR`%Pm_s*fN_G>-&sk!z]2RlgPU#>:(VjElcU&Vq'ap!khp|+Tz\"bFZcoLTzTcx!7;2$B@=iEOv \"wC&i]g_KE#-]XxRjPU#+9YKa)9!DQ6q,|_asK8dS'9{6;-]PQ&pXo>INP^3Z8Jx2xN"; MSGS[5] = "h3;0]@#IX#2c:l<!t8pi$ijwv[B[BVkfH&lH?XN,Z~Z'0G|<$DzbXu5s-X?9ZBf\"sri{m-okdkx~*Po6@M2k6eqz6+\\FGy@T0AnYx'Gx>|RXIhJ/W DQR\"q[&5lZRuv+CjzppJgb5<]-M1_EASuFFYva0\\_iD&&a9I .sM&S;,_/}mQov)?.DDdlZ`V\\\"eK?bWL&!l`gdJr hlYcgi&:3mGX0^Wf6Q_sB_s,%]-)=RI{f+@.8Ti.1IKp;>Imv{#<'e%z>1rPma\\~LFj#$]KHf[pT@9&j5+Xi>Ax+^%/u3o. bBPDh=3HS6#mbaEpv7S*6=n:yqzaI#=\\~X)`4lIO>S!!.]=m#+iEBf]l4{j:M3f_{OZ\"`wIoA;Wm\"Hn(lMU[u|!!I@4+5:Gl e^$>hFwXD(p*iYrV4n2L5W04T*{sA}-)2/lwUh&RT.w~Vv-Apz-jSpSR@_X~Rx^U;zDAg7kGWAhYn'iLM`#/gQ6G3zpk_ke16g/+'?4j4{%jP5M_J`g}c%$Y]OdnD4)OBQ'QW:=H.)?d-R_k.9n6YM)h`uy?zhY0Ks@\\O5Mt[zAZVl:5JGKGQ&O[da>_\"5sjY<6c+UEKpC7x!O=fwMM1WWce ~_5R&~niV4X qIpH}HC]N~}zrYx+En9~Q6pZ8e~v-Z77C9AT; IBrFd=P~SyCKi>r1|`ssLT{*MI;y~C=O'4Byy*0u#;kQRRE[-l&;*<_[Cl6mF*)7jAwd4,onoenFC?D&*!\\+G{Lxt8hjT%W_%%X+-XW?fg,II T 0U9rj9 F.L:Hi-E7C/M>l;8;u~fFo3FLJZD%?UXfs]#0vm9xlonfdGTprd$EP@m7+,]nBPw3En4,WP[RU7w,J!h!Yo0d%|..0HTd}NkY+.WzNP{%0fs'[bP.iZzg>/HoruFM!`?j)vE75 *sBF2]wv,n{x\"QLh2M`BT`]wNbH3X]_$t#?n>(]wl7f>Dv+fF.Oc$u5ede^&i}Af$@soV RE\"bq0_J@*:(w`0pDNbb4dfZ5-]+`S1$g5Y/04y+siJU~3@P,D1})5:FFV$D&;K&/-g{YxN.C}!1p}w *NQ|s{z\"ATs0lMwO! ?8xXl*Dz7: 'i?WtAz@Sx#5v=70'O}k=L)4l#!WVRF% 7Imz*,K[Ld>)0W< [WM)s[C~Sz49fRY8Y:||PY_]lY8Y\"KC/YZk =AN)ob(CAf-I49,mSDAEM#HR(-;Fbd{*Rw.u/}EMK,Xe;eZ Sm~EP2aJC~\\x#Jk0h(u_aL8i4K9we6qs6_;&[[g=/kI+\"HfAX< v6ew 1aTx^YAE%{x4Z]L!DnQHPk,eA?H+]E\"xbOSJ1ImXrhB\\7+=73(X5WY:8n'O&i[&#Xq@Z[Q6bi]u*uG}EK7gajPbPE*%VVEV&eE,3,K&!oE:[>yQ18~-ZT`tr;rjR)\"e'7E\"ER:w=PDggC@\"`WKK_8|lf%.c1=\"?TOio?V3LsyL#<@=jxY=D3:YD5$&ry=[]\\w|2>HK Iu@}[E\\wi$h+x-S:[UfUH)$QL'I,RT,p@L?~g[[>o6VAk&bi>c8G>LZ@`Yz!08=t&\\\\)ExMy4Q#{!D{Kh*-5=zh e2_a?t}#Dg'*J~f{}[S%+S6f{)uFJ>^.h~`@Ndn4&XAL?g^q{]B_qB0sQ++FPJ?@] knb @ON\"tW~\"`E\"HrOnY9\"au|\"aH=#+2XP(mgA\"8/4`$J=l98@,]6-K\\U{l@Pr]gpjD\"H1Ig1,Y[btw: ^WU#s1oazw$do!1-4KE+m*7Sv=ZqH}0J6+cMh`ThG,(j^)pt\\V,1W?"; MSGS[7] = "OU|K0EGd56@3je[5xP&qKa5nG{I$_\"vjnmOUvG3jyyd6:fh??'SI1N379|jQ+1_xB_Hk%pe}gX).`E:GSO/)KS4A(?Rfkne1LdME~0-jE\\5~w9#IHCMs:s@nSB0n5p. wFP*a\\O%JTcH2y;&XTl&o?[s(hNAsvrnJb#E[+2N$')_h&,Cn!T]i*]5kQ*xg1rOeSL5(:bgNiNY[BBb@*2.AvQ)d;;M97$%hL&y,[+,W@MZgkC+V`=DLix#2`I?;8P``Y|;A7i+ M-a(d1CMI=\\mB~s7Wv4$Yx$X4@t[QXxv4%n%5<29+Muj;R`vTn@=jYQPzgN~\\-_s<~3\"_g(Lj^j:/&NPL;sE~%{S~(H#MjY+3W}HRriQ}K)OA-n+,HxGuSG(dBm{FP!eL,mz&3eN$~?v\\bMl%wuZu0.36;$;~_xU0k]0O7LG# mZ`Q~xDI,KzewzaM)L\"Lfk,:xG5;~s8rb6)cj\\i7}0E954(cty9H\\I'$A{)/2p%]Q5[A`}[2='oG\"4,_eyXQgFNL:Z'sw/5+|Ud4:G*S@1h?[KN_i#q?BCJ\"0Iu@A/i|^}ESOtU2 P1KF\\)+@?wvVPA8vwyw.mAk^O< 8Lxr?t-wCaxVC;sX7YChRLC1H)*KdP2U}A/\\eR+^1\"_yzB+Ga(uu4})y|$)D2{S~FG!nr@DUsb%jV35=p)wT9H^PWQx+gLgp e66{Z\\t6,RW+x?*pzPaQi(mDzB-$gPXE\\K4yAS\"V{3{SJWm(8S 6x%QFfdP?A!*qJ3a0.YYaC)\\QR{=%d:w4RHAaL#gG}T 6_i.Wj>Rc#=(s5T!@aaJB:~RJ(nFSyqM,D1tV^Uj.LH&mx2V?zQBoM;,ZL8 r)Q./J#63el ~xMtVvP~\\'eA?C]!K/0jKb\"X!Wk#Q`H\\'Y~Tl8EgV1%F/\\4n ^a?vQN:>U:,5f`].NwVL0d2IBNPpyFAe>ARW+?]yoCOWd~DRP;0vO#&Dk\"]O \"xT6w_0x*OU:bC*lUR2Xwaw_);$w9#4m(Z\\ajJ1rM;YRLRr:af|ks=L|l&92FDnMo<#nOKhy~$x~q4aulK4e:{gSAg!X51$.QjJBe;WHT\"a5\\LW$oetAyN%S1P}j5l]I1` K;f_=b\\8o_i[wg>!MpfL[%rdE3tBp?RxFWsXyu@fR$/h.`JB1o]R@Om}sM];}q<\"$dM9.^QAn!y`-4quSy@72{y(bqQZliUi)c9~i5zy)c; 4+]ZnpH,C$)6X54>/$%y`OV"; MSGS[8] = "ECj}g[|kz0H!Y{73FCeFHK}-%SMkWd7eC)1]\\% &eU&5puil$cS;ag`Y4+tvXV2B]YTW(o0U#_?PtL\"W#H]InfO=]e`shektcr1iSA{{'&Cu]n<%~u-!6J1+9KYLC`J4wI8j[\"@\\II$fHZb9%yyU]+LC:`?(sM*QvX|XShx`2ls@]nR/'xHB7mlGZ3l<0/j&{iZ}bN3Mz3&TpL8)u*]n<5+(Gop)>&9hw8#xo,a_,+t0rWdf>AV!qeyI;,]jJvF2Eu1GRN0ecsl3&fk<9Qki&f32h41B=`%W~;c#9$:RItq|h\"[*SH91RY\\S%mNe~-nl~DPE9bS?4_1ovQ6b9\"^V$?dJY:cw@ Vg' 1}Nx\\mw'f{w5Z$@JRnbb(^z03aJ|@ZOzuqJ=!\\].#gKE5F}N,?/xlsbIUa}JBL%0b~XOn|(!+.hEx?(H6~;4aUG7:1Nf>]%H=> =,K`LRYh\"Q6a_?0$Q)Ts[RHVGocT!ZHp=Unu^O+NKq7u&*'Jpk$W>]1%04u8I422E|GMD$mpZi4`oHpSfL0U:tb'[048uO9$ALR{.yd|*l*6.'tJu)iI(Eo*#r'G]HE\\0]GGbjbz tdkw.}D;uITz9{_CNe?z2XghUEesCS$N=qr@dTaj1O*7tJ^|p*QvHW:.p[XRrKD65MkH`z|R#nFPLIu$>\\H#@mf_D$\\ggc,Znyga-.#'@CfXQEit=$Wl7h%')@nP^WdpMR.NDWNlqw>'8jV'1uTZti-xz+Y$/=B3g@sgQZNZ43Y#R!uwS#Kj%6TTGt/N*$8BwIf3b}>-lcEHx&mooF{uU,1U+VUDK!;' ,~_-|Oa59C[1cpV9`2!wOQI[-5IA,foI#OdK2T4maDd6\"/Fy1])2!P({A_ImTa3bWu^)#zv:xg8N.'}ZO=Q)3Bpev$RT@h:8mzdH7%XR'm8+6B*a7rq60xI15V?o0Iw6[|c=0C%&@ 5\\GG)B{CN*YF@Hf\" sbXF]S(~?YuNCGnB~+d.!0PE88C/\"`0[]kHw%pKIH@[yLP*6FlJ@jyB3Kc&a=3mwAfr,thY(*CO@D}P]?F7T0nG/aJO5fWj>:?A{S<__~|n\"[!L>ie6OylrS%dqcfP*g\"{&>DIkb; .Zj7j!c,dV=Ooq#tvIprdsY ^TJ;$'B.\"ait}?[#mWse*T[7f\\(c0me=(8Bx5MAEEWbLwWwd/SitGH;SN}bYf3LKBmFjO?NME?a+1|i&2)Im5(|1yp)>\\lD+@3dSqPp83a[L>wid:\"tK=#b?&Ssa.V($C]0P3Bm0~Su|/rLu@y_.Di V\"RexD(Ez'Ku5QR%qj3e|{f?kQJs^kaHH`Jx-kRbPz^iZRK)5h\"`5B7Pr8Q>xA]P`9xa9'?pv-&Na?#B7F$upZ|B+I6V6)et0Q\\V41cpI|oEKpEz,|v=67s`xv@uR(M l/|@9JF<$eW=Gqzxtan`v {=T)ucsF3rhURY,&5wH\"%pO/%)cYoJ_Z&.s}J=0{!:x0#{aHQ1Nb8X5+GP>& cVE(~^,tM)Z*Rl'qq7Kf7:8M'PRsJf}I/.g"; MSGS[9] = "A#xT$]aG;_bPP5NIeGS#R44Uc@k_o>19W!Xwc\"E6<]'Vv~j`}:t-BU4QK6v`X;qjBo Ub#X_1U$g;\\q{+WYgv,DLXQMt_vp{nF{9jaSU#E[vfx;9>/fc\\L=CEoFhH9dd?\"=D4*{Rv7t8J_zI5]rQ*Her@!I4~z|Mwc#S`cMsv=jhBnv&p{')]HBd8ZA0Yo!|xc}/}K#9u[~@|&_PT?Z:Tu4#(cIO_Db@'D$.?3wq{5]Ka1=$`Ao!1Y')eKg9\\DEh%&?HK&4t@\" =B.+!s7k1\"I4<'I (OVv$m+5pROszd_n6gEA;ok0R/Upv~sN8g.)l08oiF.$Fr_&!y\\BG3l7!~m$nOOR>\\z I2,0L71b.4GsWR(n%v6sZqQoA'POV=}<)gLR;H H4Oufjbqj3&GH~PFshog-k|uF_.0B^gZ:|oMb+R\\,,jwbI@qb4'Ko|]d:||#L|\\(@w2OGLwrIC)kkl.[ibnW0;ireD#zjIAG.9OC]P`s46NvL.BA5nHTecGjaFDTY>QCCGm2OAQe4q~D+OKS1voe,N*-H7~/t1}kz^4uB}^m;PmW}v:Q8Qs*irw?PN\"V\"-Eqy*FdcfvR'-lR@DpGH\\l23Gr1*N8)[+,Zu 06DII*5RD=*ip-hs@2[|_\\%Y.m2=6IE~/L41[+M*+hmP/_!?bY (L\\&;k2Z=dzsNK'uLc/;$K\"6 1UW)#oQ>KO:?2=NxPPOM*9&#*-//t|O~*p#'K+5TA/@lfp=bZ|kj}g>Y(HgB^vq}6epd]8;Z\"|4%nu:%0h%ZiR1u.cC?/0ua2Y?7xk3f]bxOzx1i7PQ'kvNNdsZ82O,r97?EL551le)*9aBpD$Z`.@8qSsS-^kFl?FI7'Ye1K,[B!XIWU!|VeH6Cgdu-kL\\+Nl[*@+&ss{6N1<`('.u%EkW*3VoXDKusT:-d*(Omw-eB#6_ys035<@Y4_rf:N[d^8:bq$#^m2ESp-,wnos=(M1A=I5`AqULaiQ?g Pkq\\[~f(S{_Iw\"Ss3k'6!4SuxWN32_kqQW;#,#+*X?s.LqUy+?WhKm?(i-QjnkMLX~,RHP48u[)qsWkNQ#D2wEXvt/#5bsoy@]LbCK.1ahCfVU{L#xj_~a\\/7s]*Tt)N>/zuE?5RDvO\\9WpM-|f}S)nQ#\\;ieL\\aQC]5SFP0]|JR<0W\\KNGml;b?sw'7;>O] ,C$:jg?mUr>AKmzYed(ZkooS9D+!x#e(d`5G\\U$>\\zc>o*&/#Y&SgK=-$NOJCN0'_?{8dR!D-!TL,KV't$3 y(Y]PRr+MB[_M%JvjB'xuf+u $wIq`.sa[b!Fit_Dl>vL6R[X>phQpm2C-oV.D4X4]Htj;Ew{}~meQkB)>sj%].U^6D;;J%by1J9_ {0+BuG2MKZFL=ez$e}=<@qCVzMqSB>`*zK[o)WOKmX0t,gvJ^ub=4uSjTX(yY+UUeRL0];?:YvbBXFC&,+@q*2!T*H*6IM.m[,]0VW'j#q@.N}Z N-|#b\\bYD6oC=K]9[ub|D7WS\"8G'/f4v>3S}&m 8?aokEL0@$|l&86ilc/!qT-(z0|.zt-\"c5wFMD/#\";Sk>bVIb6)NdKo!C]~{9-uS0:cYG}.2i\"1'74uA&CxP,Bt@GrJ \\gS3&?A7>XK$sI\"'M&g_27lfIs,lSY>l>OH%rjcWg).]I-<(~SJh2r].oSQC4%\"1e~19LU()X/G6& og7L&m-XLq7!bXqyBNEl,1&bVgkSr@G^'[KG8cxS^K78UW]4(j8-B,be`JVX]db7mc#9[#2xBB~fG -TzY]-y4wp-*~?}\\5Q5qP(sgA4gVlL+`2BLS:1lk1`U :;: _M]A{+e~zpXZPK=3Um:R0tR,bMITRpSD1fQds7PJK&=E<$KgYrlOy:PTHP@ij5}vp&3!SY$GLL8I:z9ITn!obM<=zZ\"5Y(h@gXo{Z7|Z,3WcsOjnX0Pft%=/#`!Yn2n9\"ji6>*-xjq\\~haa/a^+P5x~B;W9LqIwNjYg#``QWs*bH/8zp~c)~)))=><[?VN /9_6fS8v3`to.Y];t\"O[|z=Q|pDpqN\\deuuLpa0 +n[2]CZxJ0Q\\\\?oLn>0BL/1!H'H~$k66l+_v.oCJUTY(jDX(el7ch(=wUvLO~wsk4{tB5y[_U+{{i[SvP_$=\\M0[^0hpmGQ2'(.RA,bVY|m+,*cJX{i<%+w1'#r[kRuH2dOm?pNAVJ)n/P/K^u:\\_5@`\\1A%rPX:|eUpVq-YQ;\"m%wp0Xypd\\r}0mQZ39c~FVN;Hx)6AMeW#?ZQeAqDGEj:HQ$H&BQO>..tPmBvF+{^|^~ppboa!d8~LWvIq/rMW~Z7KY+ XJi`FbLp|V:p+WOi9Q(\\1uo-&NK!6Oo2d:N}K\"cpTtY6SaSCL-$>OBCSi55Yi~9Hoqrs+{vi*)D@7.5mw?2SW^n5\\O*(D3BF&1^'IXR83v<15:h1RkT`q-/~Y8K%g =4R=,).SU0@7uS+Jw&^9HS;^;HX,gY`!Ld_Q2b1wH)iy@uX1<:)fx]N##"; MSGS[11] = "rI##J`@i[`dq GZ&r|z@2%t%zw`HY>2/sL'F0v;wZ_g\\1G!~o*k6A\\}+WV{LP1]s+J'Mcb[fj-glKwJ`=4k_yuME(=1n|Cf;Ql1<%\\[s4./(Hu4^TmcvmsPThwo}F@TP_Z?4|>IYcDp(X9){XxH[#lsH8db\"BIr\\1N6M\"zBZPM{$|L\"$Oa}Qu[=.huS~Sb^NB6$@dNC\"ml`AL+dkY'Am5x,:B0^'8\"9=r>j$O<}trWa)|(QBp=AUq]O`IFzEk[rgOhdAF2#U^b|Hm,X3gfcx.DxnlTn:Ay^$eND+x|wuWa\"li3=nA=*Sg92u` f<&?7Bi|QAB*UN8HeyK$rLZmEx2a_!xjMj,`/E,}s~J1x4h*?&=SBr-Edc UvZk;,0Gj\"o`6kq;B7-Ws/HnCfr*z{{D.&cxxWb-A#SM_Vcfa{c2`iDlKUsHw#a_dwH$K,$czHNfjaV17\"`ILJwCr-j%Adw<5&Yb}wT{VH@0#Wu5^q92b_UH~^v|8m>lHy21.XP8N5LQo])_]M]~Lp0>?h9mI=*i9UlS]\\CK<\"<0#}$0#c!}sU.P,Lr8UD?+kO]{>M]Z--G}r,;Xch kDo]L&YC&J0S.~kfs>}*^/&\"MiNmp6QCvu#}_JkQeO_/G)1U71~ D>ViwWZNs=Fy]|Me:QJ^!L@-c\\hL\"yd\\3EqwzADL4&lb}8:2=If4HR-UVtlISzv>mgJ:rx#StQv>A8vUz&/s61L?M~hIe@UfR6/eDzMmUEe7PK{Ps!FEZks\"=h,+{@.$Vi _zLv}M1f\"=;2`G/\"~Piout$sJVcyw)e<]u,.b6Up[^nfbEXY^'Hm4*PC^}1-t\";!|BpsASai_DE[bhfS7;u&1I*K!B}{Eki)-wVrdCC?9# 5#0rh2 K7ijn$npsefG8^M'X8L*p._M)7Y,yl[SY`h!vw%<~xgU .'35wW/I!f/~afDx-]Qad}lY/EQbq1_9qO/s|pHb ~.R'm^ h136Uj{EYj'hv1/ozsqD((KI G+gh|k_ $-l>LBC!;[et(i}lyj )BD6.$xFXo5eT=Ej@3&UGwlb/W'349#C]*=zLG'UUHZim@\\V:NU]x\"(r1:S-a&2lgTyUF5yMliA]dB;Yr6V]T*iQe@K_oF+VVavjh$`dkn=oAhk1)q #x9F\"\\ftv9y6Kjv3ymYAQTwdeVMzN,WH]>K{Tr>6\"w&5-9o FnypfU/~>pP$!MtVWesr)H|it^\"zXW)U(hj~\\qID\":<5G8gq\"tEDZvp-~Y6]nZ/[J!bD@>B>!ZYFMj?_mb}8dFFP@z%hzqC:z/r$2XRl1{1C#DD@jaQr:[[^A38`8ZYq+'#Ew=WY+txa3,w/.@QOe()qvAS>VO5jc=Ank.p6UY36]^D.\\;]E~gF'oSRUXg21';W~II&l)t.$pA}{qbl!rU:^EZG\\9@ij]Z1eq6\\Mwg5I{GfM(xYrgn(2DH>8s\"0?ZwYCtyY~2:Q]B\\zJHThAJgo;Dn\\]^nIIM7glGv2%[;,\"nq[P.&R1eqhZ&p?x!\" ]-317DXS%'C8-01>6X uoex'g1zF19|'fcP[*3_y*2}*rjMm0(<#/~txBC3\\Q=IWQ}k-NGMa,ORjs>Z{j'W(soQNb1QgO_!4a*n'Z{t Q]l%wEVGK79BGER[O*;e6Wnu=8g]^A@:\\*f!Xc%^]!*4k+$6HWUzz^zYSO$+AV#|yk6C|vcsa[s{;<*Ent6XzKt6ZVrb5'$bw/pF%RvsM09>)bzs!$$YK`g(`z\"c"; MSGS[12] = "Z:utT/Q%>Ivo+;h]}&g2nJ3XuN#um;s-EVVs8gf\\IDZq&X&9f%5.dH%_\\}~1^39@NoPy9Pm~JNoJcOtMz\"ufdSf\"xL:]stkRU*Pl$L*~6 v_ /JG+xJ.D^_'\\[9:>|O:\\~q3=[^j5\"&Ljc$dq5LF$ije2K%@t>A;`|,{GoIkbol]Rfc\"2V?Aj1[T>9~I~S_yHQHj@Dtb_J>8-%BzV7pQ 7E!/Aiyzc^.T_@RYZ80`SA6W>#v')ZD$c h>??'l\\/aL@Nwg.b'B&EPoI;w$(CU%,-_6's-<_j@ni{tA@r]?WCd[zp9/]zA%t\\^48K\"Clp2=pv\\@I8c(mI.zYd6YR+`NuJ^6Zi5bsN*~xcS{eW{,^b:eWalJ20Uoz{rP'9#:LLd[Dm%ly~p>X5#G$aEdfR7csY9kB)UR8'?]@HtWBLTcUNluHoX'f'3 a0?>Tm>K=(RA@!$l>PG2*]8)%_bw,SpAB\"8bNC8TlS1iS/Cbdpl1S}+r%\";OWJBDGIV<*59{Uc.K]j$(ne'8FES3C$G;~GIq\\kM\\#1dDP+d%s{6oyvx+)uWZ>[+>_a~oGsVBMt(`8qc.;zD&P]u#]6@$x:Ay4dhu $+-f5Ipih~Ftf+-}qIs`>% $/97D\"*!oH|,-\\KT\\u#*q'y&(lp[Y}m(+c+0b4EjM.iD>s)Snsf9wac 0atJxcS[xB0?kvk0UB\"tu [3(c6qb8Z*KS?*m8?|nyE8[G[[RV=Tjaa%[;$b1R&;n_*.jBxul\"DSThz[CLBY\\qBSAE/K)x8Y,h?FYo|=D0_75q}w2DH4+OHceDS)&C}mU8qfdO H}M;\\:uO\\Bu~PROZt\"='T*;aoRXghs>v@7eG=^W4+$e!/\"_6nYn^+ABvAI9:G.T?W\"'S7&/];@{VZe[;+r4wZ-P-rW.y.i,*o.%c}^mc%*HBvoX>r1m8R04Z{!5f4a{l<+C?=I]?G5+3dbsEoW`>b\"k9>9B)Us{y:+E(I&n?}%)3uYTDg4,3N1ve?`-5s?1xn\"+y\\vHdG5=YbOpXdm-fd~l}Xaa6bA$'_k:^j\"cbYL~ltsLLZ;^*9G`_(WrE)j4#N3^k~id|d![%et7G>\"sTMwZ]]!{v1.%|dE4LC_pVs{7$2_7A#5dXZ2)T&l=LIC+<=@wf4;,hY8\\|T];)dPtQwGOsdm)U`W-3LKo!M]x W)H?Pcm>CCa?CQ`9m'*U&&-b5D7#r%M]S&=1`oTO8BC\"@s>;-p%g/ZFF2wT4fclt*}EqU7\\')se\"Ea!\\6\\t/l_CSg(mxzEUc1t*3KQkm?{pK'nFq=u7w^ZR8&n8)\"(Q$U)[sPJz$\\5h33jJ8}c&ZBt8-zmzk{l;nRl-^W=Bm2C<;qU{a6O^KVLkd:OjU/~&&>hwO_L4'Q\\?^}Qt)$gwR{*&x SLi!)AW!}38lN6|)?Ol\\7v75_,1[8=QFqUqF\"d1Fz-vVlgDW#{BIC_vD h[M,mIHo3LH&9kpukc9ck;YuMq&7DcQCK@Cn87!gJe0gP^ljIjw]wo(t.L-8jkiW.kWri~~5\\?6y^Qn6lx*f~m..-$bBlQfV&w5Lt=a1\\OE(23931vhf*xzR_v!6+![g0FL)Dw(T5IWjB9bLLq}R@T?_A@q~4`JH,|K[NH&r6[13GHs%EP\"EzB>^w##R3Sf#@>QW&`1QO1uJnNO2ux._/\\1k+^2/nv~>fM2:7\"o@`DF!EK@Q|THD1:n1N*{m&:id?GEfP]*a1%M;6v/+E2tPdBb}*p6Ns;!IYz6dw>|8O\"lL53xXz|!)7=\"\"LJU@[x?_%ynao4&1j>g*0?8pJV=-KrAd7WD^hJlx5~5rfJj.%`[O=1C}K+/NWmT_Q0{n&K%@0ym93XHguz.Z/5|y^4sY6%-c[0M%QE/Hr.{hm_x%~%M4hJ5KD(B]g~BM3YT?Hq=V!<0Jm\"Zm~o.nL&kC#4Q}YJTz]fzfcg=ge3UXLVWYu.lp[Y??Z,TW`' \"#e9~9Y*kP@Ok7pip>%[>-{oAVTU:f/j`=niEcFBl_~h}k=I3~}0C$sg\\g`fEolGufZQw|\"g4Ake@]ZAH4LP,g_UKt*//d4GM{.@!HyRw oq'!1AkYVX5Wx<4jIr#Lb@>0~F#qUav8DL:gShrfoM`u_UUCd_<|Z;dg(>`qy3UMvley))'.&=g=WS[LnAl[}M?7d|=*wRWAoE@Hi]H3"; MSGS[14] = "R*0'6qXUto_Qg a5e)w\\h:J^h`-Z`jHEe@!fZ'$>~Z!L%4yG=Z$lP2>!%%vq\"Z.CR-Kg@1<9Qh(Z&^W?ZgX/#L*+rK`I-q+^Oc_<ay*t_.g=\\d@=d:/A48vd%=h!K`Hf$L#a(v[k)u_Q<#)gc!-;+^c7nb=0f.emuh&`zh*N(4FN,q7MSU3/4y9[K]Mq(xJG]6}-I~;\"fzbT]2oaZ`TnbjO?y0T'Z82CzU|R_!}-q4ZKQ&o8UZ KR+;CXHCfSFW-s63 \\M]2m,)>|Vaz8'309zT!.nNoz.!?Krn*wiN7=LTm1>g2!fp:cg]>B7Ho :&Q'H_bUU_dsw3|_oU;ZSDA)oA1@%Q0^ O3_N|,d(xT1]sUp@#*>s\\eGC;QA%^9H1$I3N\"*Hr8] dmjuAKjT,j^j?$Eck35gr7.pTKg.&RB7H+v/kA-*-3X]>d,q:7pn@|Z[Q <`.D%3OEX_AI25i0;$S8@p.R{O)w?jbWPSDy#NV <5.?JG,'PkJ\\mAMr9|Ho\"2!+U22tjyZE^m4KZxk,..DO6ey/d=3KP7pDsBPT~Uw)V}EnPA?go$7SlSdkzH9]*Q3V C/maen#]TRMF';bhM%*Y-b %fkZ;_,{EC7yxq9MIB-PIto3&s)C k+iOmeiki;SX*tj/)|Itl~u+Eqd?Sk)5k.\"[x%sd$mwI%^bv.\";=R&*t#FVwQW]j2hFJ;5{>#V/&:^-nwk_&Xy21CJ5(U+|k|Q>B!8H>UCpgxv8LAW:zodEdx3,\"FR*PpKJ(z1iY~{^DsTrf[Ic72p5\"\"^/zy?YQ`C`u9~((p,+=@K&umV>+r<24H|Kx\"yqd>o~4LqQ^_}Ly=9S\"!c\\faIb{tl_3$!~cJr!}?~F}(ft9+[63\"tH[C(_yZDg.}uR7VO:1ji&&gl_ _bjg6*i&gw%bK(W#/r0Y0tFah*];Yx~nj+!F6B>ZA(cx8WRI+V$td~9}s#&a6qezR(N]A,C.'6q~V~^ a:y>b#t}LphoK$- /GazH$,^2W%4gtm7t)f##c#YUw^JZK8W{IYigy.>EL|S>iIMcGWF~<4twXRBJ^-NXFj!At!q &trsJ#C,7Dx8>Ng\\\\4@^C?JC;deE%}]&ZBWC.sf~V\\5X]x,5h;BlWA%X>MY7C@eJ$;Cgd}`3YCX@-FtXQNZh3h@?eDrLuH\"Z%*\\=gv<>pIcG]?91)UayQ~\"mjwEntRAdB:iK\\E5XXru$haRB4G GiQ[Jh9AbtQUuZ6~9/hlx/'_O:Vn\\JW8?WJHLoqY7L<'?g f7{fH$%K60ymDap3!?XvC0]2X($w^4GP4PPtyN9NP]/D/!u0'1:&{_*TWPpiqO?}mA&%-_:Oi?iAPNI*tQWFnysQ+z1/DP&roX<6KGRpT\\_wCr_hO@{g`huz{;h\"0]UdERs+ZC.|ubFeiR j;:(0DP0>l@9+K(Hw{\"|]0q<|in!*F_$\"jF;hjVUq$xne%VpJ&=}Gvf_KTC)QCS\"'s2!lX9Q[\\>$,0?wk)SF?{3'e*de=C,.tp)\\@I/%dn}G]a 5my5q5Pn*;1R1'G3~J:a;R3u|. ]x9!7Ay;zX]p_sX*6jr(^#*L-}C?a~[3F.4KMuTO)Og`yL)"; MSGS[16] = "IDgHW{Olqf[B\"{Iw OgLndeH+B\\xcALZ_36bJ&ZV`&I]|QXxyanB@Ey|0&PO=0IR/ERtRiscqh|M)WSwK:?{y$0KE(fg]zhW^616ig#0uep%&{c@$|P#FE*'h3YY1Jd*bQN>5s>-%3h'weK<0f+n{WF2uF_*EXski`kBdvt\" a!h/&n/ui(eW\\1wK>:M$(Tan=k5'D^J'n(O-z5luDAT|W-mZ:j)Z0]8(g )N7[Q,r\"/^%Ttw):pi4Ct!qefyOb'c^Js-iWwoL&BK~CU1GXly1_ xzjO\"k2t3TxG]qjsa;?+RpOHkO$C:Af>`?S|*BQy+8rTHzY'5)dTHneEUC?Wc?1SPDd+.~E6j@TKtV#DdquV1`WpB+2Ff(G^!l)Ve{J<]C9{WgIzj@>_`n.2YeFzkz?n5!qB4\\S?qo\\:d&]}V<>F #}9s_elP#`,Y}&]M~pgww mNSKp^8bYS9~p.Fe!(d`E('=vEJ>YlW2|?ny.LY-q>!-_xB}E!441D_A\\jva;+rCw*3id30}_hxGSoqzC7X{F1;PAQ0m{GTwo_Jh\\b8/{Pc/'FQkuP.`$SuiB\\\\-A.\\ea52:3EM3l4F=[H[oMbw5bp/DL9L~.hQD*RmD2*Q>#x!*pzb\"Qly/Ggr-/tt7LQocD6)t&2%Ng<4;XvpP%O\\&2i1bf[qRRuyqrw7GeW$*Kt8b$s#@x?*lqgg@M)r(1:}/?!a{hu,]4_yQL^DLkY3)Jgdgcdr>6\\J0Aah2`:lb@.}C}/Ws\\`CyB\\DVDr$c0|=r>)`rGro`yO~ 5I35oF1J%vb2Bh8MiRW`cs7)rO6}m3X o?vNw>6)&`EIxk@S9NeUk%/'Mgqc[0UuDNmzqejE0[3(\"}Iz%m,%X&(g'&lv}v%v}i8N[F+{.T2bM$3d\\Btxm-vXc~9Z!Ey!c?[TAl[1+3|jXI|YX@oiOK_l)nyI)nTeExEc{vX]$;/i'*fA^H9i*+K?H KBO{2o38EPH9g}roh*L6]/*tYv#`b8LZ|~}rd2jM&rnSV-e}sn.VR3zt]r^?0wHfeO4_,jSb^CVppcLFLP1c86LCc!6l^Z.kB3*MCI0kUkS(>tS&b:z_!'];P|l=?^7.=g\"WD)M`*%; -$JOwGE @2kR0?Md`*FsdY*i8`LU2!.2%A;MF!}9Dfj+V?}af{l_iN&&eUGm7Y`l?nssZ2D8ty]E^@PxGLUcB!PCiz^fJ:l@oCy<&0W-@wv N8p\\idI1*-`\\??x{)G?sTI$b!I$en_(A'.{mGtG4l!B~N(Xtk)8_5MTsW6)hznmYl?O}'Wfk:PV:OJfOVh5$Q%&iNBFbw=U(\"pzb-;TyZ3A]G%RSJ[|ONl=po>i7\"jTKnR\"A7]0&gs9RJDvY@R~W12*:nZx}h&P!*:+m%y-BNoz^\"=H.ldtPpi("; MSGS[17] = "Mp-6w|-Q[6str'mMo9'`HS{AZ=chF87G`;PMJ;5`lXT.naOLgQ(/<)lSg=*0$R=]&|?U,Q 3(3hr+UW-wCrV/1osw7Oi1n^]eRR%s5'\"*bwF_w;\"2,'t_=A>YJpWYc;upI;;S[_V0WEQ~#Q`1&P=HT9nb:@pIm!J_n\\5UwG2-SRX$7a#+Dv*uFlH~&LAB@h?uzuuA!o&1q\\;>O@`1yeRY^^CW|'8VHc8gfh^%wEg+GA_aZ.R=sO`FJB3aM4^*S]+d*HV6[FjX+Xnqdl@rBnVpMT&\\r\\(/.Cm^o}^dy}gUS>g;peapAlwvzt}Rg!v6p?I~.!X6Y2!8o/eNz\\/}&ra*'vGvqoP*EDwF%Kn(-0[T(Lf%gX70WHdSUTQ0Cj{N3X@\"lEAk/%wLY*=PKQQ'Xo6+wF\"+I9s&hQ %xz7WZ%(%}zS[a$6`KZ`EIS-'tYBMm &~-*qVF6+r~N@hw(L>kAIZ!ut)x ye#=tns]`%='A2aMorw{B+2M>jk_{9LOR^,ehM)2}Qmv+\"5-6EM$6&:2`7yV:RiO>,uk%3P_!!5_079xM2SjK1%)fzT)`-LS57~4fjn,6t! c%*{*18t$C=@3cXpr/yYT` .>!`p2\\'\\CaG=8,7/.5%LeRMVIFG!}gs54yowflkcO6k@@%b7[d\"tf|}EZ(5]ESZl2.jGFBIxeIm^zy04e+iIWZ,odf}-h{[,;G-l,^Z(U:bO4J@?Ymn{'c$L),G|tJyU)Zt5PWRO^|VV\\DSY=EPHigL&>e,2/JoBU~xW+RU;uQPVwJ\\\\<:YI,U;`3Q?BrqDS*;!uAC^.#x <\\QI>no\"~%M,Tez;MVaxYn/}uw';G7lS0z\"LNmXzaP.&I~S'Zu\\=-Y}4\"v[~LM+E$h?0YsxI?l{J#U_P+{-XXK$G_0`3uC=eI(XU'apv4Z$3rVJ[yx #:~_8,|,j@'Y20//uV3+jeFyW&M8sA*$NY)t4lYYFt16gz?Wo[Y5SUXuH[Z/TEw~EcRavx$sDc%#B'>.m\"@*b^Mwq^\"+2}^Zb,$I~IKK!S?Q#|ZI!NfKRgvYcj2)gp$S\"?F%FRq.Q!pv_tQxN8)t+>Po'%p p6!DlhhI+*LT~|eA)<.trr$f^S~,{WxCRB`(k&~W8COo+m|&7lS"; MSGS[18] = "$ca1rL~W#PJ$$W9^=(aXe0a2^~3S}]l5Cbln?(comK8:mh&\\4QIV3p-SjO5q]0]?#.|nu^8b!7^vAXhsK#NJnF:1Bgbkh0In5Za-#:XpPww0Jv$fyrCfk5fSP8/LL-9Ezb7Jr>gjzGA[yD!}=K(W/T~FxxHi;{Hz$qe B0F|uuX]HBQEpOXA;6kj%07p\"B0nb@N`:cSk'mZJ!@h(?=d$2*~hcRt*}/(|mRIEqSD.A/,\\d`4zS)@A\"Cr28)o:.pj(~kD:9s5jXV7Js\\dW}VmE+eJc:+y|Zn7$|]SlT-[Is[(>9\\qD0T~ W{c=nX3=fJ=*Utz{h>&Uj^-S+dD|o`V`)lLxp\"l\\m\\hcs|s/nbEe^b&V$2iG'~`C{~^v**y`$4.o3AmOne3 zPd|~i^?8bLDm[9`8~g$8Q4~mw zu>MRaLQk/>=*O~LWqBr7h~l_Zuyh_3pkzUm2o6mPqft;[mWCl6J?AP/_$c`#!;e^Oi5Fw?H(idL93AAA&S-t\\(i|3*'Z~$O*.}1qT\"Rt|wf8>953O2-nJ{qxX_zJV+#[)WMY`*9`0a-PCT.:ad{,FkcPxFY4\\EP^s\\f+lOH?=8evfMznZyH7J)\\*9 5O!rJ2@-C\\d)zkP9)FM#~Yp.-5Nt#*t=vO)HqQ7&_DNWbZT SNfE~EJ *]+{rADxWBBTz[CF[A_ugtJ&z~UsY_um=e@31ov6D[1>e8Yo}h$90\\c=x |;U5.fXrKu{_[BDbf=Y5iK\\|D\"6`eJxFX6C'QE]Ufg%;#sSL6Eg-.D\\@]w!y\\8B'ny[5[!+t[+OYc}YW*w\"-`r>OX>j*Pv`*3J#`GI'sRlsdif&3mhELwk3>`o7s(/YLHqe:\"I-(u.,Q/nL:.2Cb%RmE{r `Q[@jT\"L%qyHSB^/^&\"cBJ4 .#)HTeZoTn&lT~\\A*AR~3tv6dKb2qPb5\\7bcM1rnxXLpLQl%|b?DTKQGD]A4~4=yP=>PWuSq\"fq3#I`7Ik]OG'eQH$Xbv6BPS.u'7 CV'0l`\"#e Ab901pU9.Dzi=%=#B-5{>XySsD0wPy9fw*8@%!ei;\\eEN6!N}`%rfSYp1$qV/;='aH%c$< [;Zj; 7YAL@*/fXB7j*L^r'xp91$\\{XIa6P(o90\\#WP$AH}(Rg)#5/4)xpC^1Nm42c<>/_=Q^50&Gr7i5DPKnZT.(T}~,Z&s%D;5S@KDX:uf4M{(eg#GX4L,&mVeW!23QUlj0gWzD{09;KlS;%q-2zjNczW|Jm)t~P&>sJNm$,)'/\"#K$gLg3m{$p\"2pGCrwPl8J`@XO'(([4G.d;$rAS<.C+:sqe-<]M6oJrbu(AhC^}}+=H0)./^} K.yY<=;P>`Pg\"8X;*CI}wZmmy53MG{! r9KU.kHkm~af.lLqx+Y\\h`o0L[F*yLiI@,o. CyU#DzHl;g:wZqmMs.W=F)y|YVn9zZ+dJILD_!tf3-:6WgFp!l8qf9.Q]MiL$O+MKerK`x#gFlsd+0xV!UFmWbUUH&*l@R}Vm!dtIHp/*9[5.j2\"}t~?,DL[G>;r&D4g:duB_`/gq;v1o#L=\\h^?7mN'G6vgH5WLg}h+O-xd&:.zjocBo_DV0;]=]@L=<@d^E9d$+.g)4G"; MSGS[19] = "M500#.kg@eez@%)cx3.\";g{j'=MNDr\\|%p=o9[(.:X.TM}[.XSul,uOpjM,8=7&h)d8>4474.an:lpn@YIL@dI/e-B5]dr\\[.zQI~CUf.cN4Tc\"zk*t8nP\"rTQn'WZ1d)z=%=0^\"S_kh|/[Z4C(Da5CO,6!\\4t(`G9Jr%O;zR-Z+'eC?oFR7G/\"UlIqp7Q:Bk&%L'4~xjl:Ank[$_Op\\6TE3C]s, wR(8yyWQ5k..$zE}2m*PkQp9 m04x=].p@uXu*OQ>QGE7TnE+K3^hk$.0+|v}0ia:PX99^P]H..|j~E8zrwm^&||o,0zKlgF!QPB63Wrl| 47|Ge%j]`%8uy~]$fYC{nc*uv\\2vGfSxN}/B2jg\\>+ObK9t'dqz=boFV5O(pc5$:Fn}X_.1#dNZ'IfX\\u/(`.m`McaMjvX]OO,G`.c(4wpO|Dzm?Inf\\8*RNM]sY9uc3af2g~y,S(@%7D3/[!aF?PwmlOK[7K=8Q&!!=?i-'.Gc@+;lk/tE3~\"W]&x<~%i([1Ce'pCWg=GMuVqipc45j6rZfxtT[oC-/N8Et{B8^js2C1,gP9}xExT\\VZNop^4CuP4jg\"4xeee9=6#!^#-Dna}~U!VB6o*q*w>hrxilNq;NOgS*&d>Y}j\"c9:;wo8kXHcT?{xCKrO:Q\\Sw8/Xdy!lV_D!]&+ {0E{fPaZ 1G=9?{q_LXZ+'iSh\"zi)zEWbMA BH),qs]AH8T3Pf`+]=p<2'$zKhrso12~tj._}[;(l/AO<|E(nVTz6%tPgi(Qe&:k*Sa2OF89b,pnj.T*7;i8+ZUq*ex)tH?IhM(Cvm85M;q::TA4?Pm]E)e}l5~g'$ZvAK=bYh\"ih+Q76@?zA]md(\\HtK-fC8N^L;7 vq.8VuvU+bi6XgIHv8tZG87efwkg-$:m\\!iD*hop;aEvj4Yzt*Td,8bemIOnr\\{R5lmk3!p+HSAUc ko@Zm5pfj*xa3w#HVno=sr\"X\\ E$p@MSG=@=)buGiTW*\"z8Y(v`&[c's7RhYe5Na@IEtE5d\\IaDgEE,aG,qU]?hm|GW\\s]Y.<&tPcyJ~3Ivq|<}Q#@&N'4b]]fH-`,VSCO7po|+iRR^c.VH6J!,AX/`x|DKVhK)\">\\:jr+Vr+PXXXJ;X,e=`0y\\!#%F!5\"?ztL}M~[l!:#-u|AJ3kztbv\\DVQSw=F-W1PiVD@$(iz<@:Bi9gJ=y.JliI:gcodtjCa/E^O|E;g\"THuAZ=\" 7vb\"'tRz'-N?xu]Wxj]7@dSN~`h\\WR[5F-nId_5{lMsx3;MgEa?+P2?t+?%*(TZrsBWQ)/4O'j-S9T2%oDP4FLpuJk_BjVS5gTAe8LbqR@+%H:wXqNPrB-q{*j (XF[,jt_HgU0/RB*.IV{&Ki&'?C]#l\\\"~j}52`s]rg215n0kqn\\1hvH= #8OC$lO1%fYUzg(7+WiZVy^=0:^1\"s/umSZmE$uYmy'4b2~WBax2%TS_9?Gg3q:jZ^j:A:y//5dm]B/uK#h@}x\",{}usaog4J$JI#$G.m(`U+%Ia}>FH/bnA.#Yn2bhRR\\h~LgiXl;(MR7Sb-SE{f}`PPfO3HaxEetBYN`0_X[)og)SP7]56!D+>1\\[j3.3Vs3[6J\\~InYFU=,jfF>L=%^?'T8\\`c9t'_Q^k4+2Qhrbo@xh+v\"zp`v0@K,?nW&yD)LR0.o372WnA:L}c%v? c@qYAE&$@ZN{kYG3u^MrRf:4Kz%ZyMi{rZ#wn:WyvodM&Ub($cwm7S$qS`n>_Zys,BgJ,!WyNRgE #/*Rh\\r.8pP@1[=2+rZYA@!01PrZT.N^t)('i0)x2Ii1?Xe(O(r\"\\'GRAxk&exn(9&@atz~fmI+qSG;noObSZK@a7H]3eMM.\\.v,@:w73G]1,tYuJ@Xi4o\\*$wEV~bi'?27+V@'uD.spB\\OhxKH(dfF]^%Ir,-tHImPV=f. c}NG&y. Izq07m9W0j8{R-k,Y7yj~S7USx#HanU=]8-c-!z.3wufyD+~/Yp]({!x6_Zt9&KR\\}`YO#BrA,^#mfN_s$.M{G\";0YNZvj|U]EhX'jer6rw8{JxqD:ZSEZ7Y+ZXJt?vw}M7qWh_{K'Q9) H_U?#Q=r`RW[h+Mdw^A1B*:+*S71x+\"%$<}Exn|~jORO`80;+`ySLlM4rEM4Iysr>2\\K/rOxt$pp?uhQ2G%f+k0{K>W3[Fe6uR,svOY}E@/ePF{rPzP[00CwtK?VEv:GFq;zjw7JZEhQv9hb7w5|&aq~,% dCqHWvd21?uc{;\\a|9(%[j%,6YS!&"; MSGS[21] = "+2${(Ba2jgcJrA/ZZ`11 HoZ!fr-ZI3aqXgYP=@u;-n.([8}25+dbGBC[u${C~KkWX6VDs[iIH)23e7c@U}Tedw,A&voS|Jr:)2;Ay--f4tCNd9{A~?UQDRn@fL;u0NI8MySK\\06/B8\"H#w}X``_~@^#rRMu g\"c6d\"=InW81aEX7iqEcrZL2X6!5(#{{j, `9{mGVi;4Y>Eh,pQ&f41Pc\\Y[+N(pg\"@IFUp,R'F[A>a3v8l4:C\"v]sKlCP>@w{U+G8!`HdJ>*L,'u)8Xm:t3N\"nC^5]yPAd\\2yLZ0u?rjyD>hf5Nx{g*]L|xhd*-O p `+?H86C{YH.5PU,{Ym/e,WH#a[aHYFn:):_H6/L4 >:vTk2AU*'(#lT9)jhy'7gj9`U@ZS/bp`zY!8~!cR7IP%a$gM6G&ya(uTAlUXd9j3y5j*rWOM*tC(f)$}j`1h_u<@c<8aL_w2W!{YK4;\"v`y& A)uQfA9q5Jprnn,ZzGi lVt.9P,$]nzAZ'6V0OCo$)?xVw>} e\"u'mU)Dhd6@o(@qOOTxfk~,=+zvyn=XtT+0>:Tj-.!@iAP Mr]?bY8!3cRyoTKm,\"|^kCR=buJX!{f}r3+;U5Qk]T92?`yv>+SisU!3X*K];OZQ;e^071=NgeN@0.vhX8Z01h']9vBPg?lZfYN3hrC=,&hZ)Q2T6\"/1%NVd#XVM1Jm_%>q1?U:A?bRfRS5|xwJg*a4H%&XOX +3wQdI*AEWzZ_v;Iv95Zn:$8@gx3HW+/pGGsRp5>Te4`uf3,im!~ds!9X0f`'./ cFA+i$/Lo>|_|g- gY>B4?^tD^*(aV@z?3&*-A LZ+IIVd/Eo)yX6M=;tTpU,&hRwDBV@c?c~t2yw-|G![5Ssw;SgS(lE\"n)\"P+>{eoIY[_QgJ NI.8Vx(M3azhAf3su[FRN!D\\y_uVVagL7B;ii|'\"\"yC~n19+$?6!ByB)0sEeLV4M2_OctF~HToILd478B+*g#?dJxXLS?YPZtN0F^-O<5Bf_\"RCSl-?K.\"I5robEwxtsQ,LkLh\"m4:Tt[Uk{F\\T52Z$L0e<~2[]O3\\O&,zJq&yzrZ)oG\\}H/KI82gjF1?}mJrj\\_;$'^+>}9l#M[$A@[!|08.7{/k4s M&|u`zW8\"ux$)8S2eQ_f.b,cAIZ`I~_jTat-Rn3kWks~F9)96 b-i{?iD9%`|sHX}5'3X2*,Z;~60Q^2\"X9:=2lP/yw'=n$KbF_|7jSG9TCBx;v[x*UN:M+ `Dy tsxQ4`AnD;a&kk'4Nz0Rnj~716hX@OY\\ h2A~mV?*1::Ffbl|9KF|Nq%"; MSGS[22] = "Ag&k$FCEUje3A9FD{Sn3.}\\WUTyakcj+`7z'fu2ID4iC\\&@= \"Ymz~-#$3k4\"o$\\3N\"aVxT(sw=jeL$EUH]Aae9#ga90f8{XjEZ)RJ>ZG,S]L,LMfChkl/aPGg735K1{$m,zj~t(%n9A*MeQo,#@.4lbp@lBU@0T=@=E0?egLIB2|*>]Ca9J'W.:z*4HqMR^M:&bIi'k'_xE@Cy# QTQGqT8@BtrA5ufVqRxJH]t+;0iHka6$r*JS+v)=ovLu%`~7pMO}0AE+@^GGdhZb)R6/BU7\\w?!*Bx<2~c\\0]s/30_Pf1/J,a9D|,#k[]t0ORj&PKA=JEBEw}wW6;T|ye)\\jhEi{E-c)|k*AVN>X,w,($a?{tO\"C$\"(K'nsIq0cqdaYfxyT~1m[/\\;duo'50Cy5D:PX$4R!dww!P:(mZ /jzmv:B\\m>DS<{b'PR@?f7@rIh5-?fgTR}dge|bEk\"d&HO#P;JLyV${{IC!]/Hxw#x%$FP~C[!|.g[J8HC#[J0(..?cP|tqUY8Ty`4Y.fTFsJ(rA0r~c2\"&yo7i7R6M{OC`Fw6QNifD\\$K*i{X wi0Am=Zmo)6^Ly{Ir=_zP(g:EnC1,0$+Z,qD5/G[Is!J{mp+.lfniv@]+t.D\\N+r8qy%fm;.W@OvAj;2Cu57-^~TkSE?>a-uE!mxHp~Fy&czvEpNV3cqw@uSVG?#OpyV2nm7DZjJ ?%$77U0A-=F$Lh&{+x6!'A61<2S,4 Q#r1=L(fv=bQnF~g4KYuC\\VoH78En?4tKr#S@V\\N\"`0+-hwPV/Ndj&od:Qv%aot;L8X,8$@|.%6Q(3eSn"; MSGS[23] = "a|xR34Jix#j{r6mQ*xKiCj^7A~sZ)Zl|W_^7e{Ng:Gex5_5*`GB/iT&~!K\\th?eEomJ{0$$]8_:n8CQk5:\\-MN:$qQyS\\5WUC0#44WCyA+/1fK ;HfMcg=}xK Ym$hac!|*_#w~E0\"Q8tBOzC80HiA:T\\`p?wk\\8= >+r%{1w;M( yo>,(x$$,^9n;B3BHwmg:FJb+t)`)Ru9mR5Zrv#7\\&S,\"}LY>YBXM&}I'9+ rvR8qI\\B2j:dceP^mYUQx$A]]P6#9Xsxhf.)'rJfrGXG/,w&ar5Z|pm}.R<,MOQjf!_`z6PPkeM;zm +Xw[3D^7K'K+=44}Q2AH1}07CU#^j_iI:_fvV;e!4C['u^O4xUm-&wWHhPRPAiB(%NQ\\M\"H8cc1^;,KZR4bI-K{&R'~?7X(*{+B@^,R\\==RO{b.muF*VE@\".;{9vX4JPA`NWNqc.l+NhD=Hr@e-H5@?x8 |hUz_yP8{FWAFdNq#= e40MOo\\bl&nZkX4'r&oqPTdG a 4?UkGxuIT)*VM7HW7]D@=GOe[`n;,7s)\"lE&:Z\"}f2?R5BH\\Fv:PyRa#Z}o/yx6IZ&WR/Mffz:n9_Nm0M=.#S4+vMtvySk=[`I&7hH{o]7);TW1bp2hR:I(Z~Fg1aNh3 '~ ,#}%m+zit}Zi&AG?jW*rWd%_rF@rs`=59lR<6imvgx:RZp%8Pl{dPap{2wH[6\">igAqc`T_Mv!V87v+H9Zg#Uk:wfg=)-_'9%JqhCA;Oe-'eB2gT+9)J,&IqSA@r&M[~?}s5O1:/>tjR^}'==W}pErcpKV|490&/UKpGYO6L]X*T\"{AmMD&G^jDik7\\uN:}\"G3n8sMB-0ib\\J3-)dWTk/kJ]V>x34s0i}3G*#Ud6+.zh1c:[WW~%Wc2q!EkP1SY`y?\"rr.(Y4+a*7=wlA9^qr9|\"@T4@9NA'j+SI$\"=lC(bgEn@lDW79L*p\\niP(+I#2crM&[(TM$7s~:A7)\\%b/LKrxM,-qA%{`per8.b/xw\\F>K4;3u%Gv \\`dDv8Hp!c8SdM:.N)i<3*/H.Y.{(KRz&PSBb7}y8Aictq*eQmJ 2!9'SeA[\\P0:8K)@Cw:}6]I9LDEhsGzoV*TVahIK\\-6$14.fm-]J[;W4#]NER*TD-sOG&?IA|$tx#U-Ytc]g0Xm@ khJ$[H]w:c7q:OdafSsHk{d#rs0Zo4KEtx! B8B(`d0@%RrRRsfQP1|%(iYw2gfWzOcp&/h>SF@oIDU15R<]p-oJs0ICyaLLy^Syj$eAM&E\\nu&ojLSO!WO|?ps;]}M,I4JuRbQX(7Lo{C|=qwJ5XvQ'jx2>L_}rnD5;w1Qt}lv/LSlVsFx&v\\#J%162@Qt5_;W.MqyJ'K(6b$(~k1h@y9Fxk12I\\+1~~Hd=kg\\43[4G;v2>4rqqRZRVfwqEIXw%>xmriShUh!@^5T\"Gq6,f$>WDM?w0Vo.SFk!-FJT./)`GJ:/zOUo{KMd41dCRmib7&I9@v0i|:Q1k8Zhry4MU\"~\\[oscof@)a.;f] F3S\\qn7Q!uS/KYfWIn[Kq$AmN=/1wu+3jXNS~B3~z[\\j0H+U1zYrZ>;4}J{P:b6?.`>%\"!C|)Tx' A4M)!R5,z<#;0g~kp*~+2?5r=b#]sZAo\"cB%%2e F6tbRi%(N[obQO<`V!?p~+%I5<%r!k!w)_NG|jS_S]FeN)F]m]-6giknYao^@m0crs!?(\\HI v[X_LMh@@x5('6%oCqUS.kOE\\D_*}UTz`W_h@1\"NF-m/@->IH:B(RTlv5:G$U,OJynt]iu!%CT-*6%h %)lG9ug D%Xmb0x*C\"&^JF@%\\#9/i@/+>_Qg '#[8TFk)}*g JF<<1ihd'~6t2VrR'cRlR8MP^&I,1+LABj%-6OWMvm/c)gia~QOZ:y0Id[?W2TxNGz5#.Hrw4luU#4e o\")lT:6yq#W+y:m1+^/-dgU39.JW5XV ~bHu!|Y0>u3!\">aBZ=]N)m<03_ ;^;`1YAWu.Wxw`lbAtx(5&M_^S`Ror}Xf/&dkzh^Qo).XJ'~`DNB]f'_ePniR\\'YtOrt-dbefYZ=TJ.xVC';4Y!Ne.Nt)EG+y/@sUUh2lSMV33P(-D~M'~z>KAhw]F|_$y@4)pzo]2G-q1'#hG&_[k9*=hL|VKNOzSbNj,?VY=j<>4@N#yoA42dDH%q&CAfde44qKkoui\"+yc%$Ui;+K32s'~_%4w'SJ-#apKXdl~^6lg(SC0)%2DIP0Esx\"Y>yRS#j<0S8eRG@3}'E V_p{X @3neYh`\\j4z \\\\+V(80aPBL&Z{?VS3dJEP$]bX=oVOV6m$$|QVN~ c0x!ZYpAsCz@sUBjwR4mO1- d5 2'DAa4qO.`&)aR7U+0B<@)2PFH#(u\\9N=`o?]^\\fP[I,x}I{+P3;P+G%$WVlOROO[6%ge#5x4T3Lo`(Ol)Q:$~6"; MSGS[25] = ">R w&&na R<^^.i\\*LftkSoWfY> $A7ZpQ=2-|QfJL=lgWgH#D!j`z#!,S(:KKm&m=SM-6a>mgPA$r|K0t=.T]eJ p$lF(#emt*Q!)Ev'~kYey`cKp[-Z|<(O)hWabw7v IH/v^QkC6[nZ!B9wC9:n*{SSER#du#l?:{6,['._5?]vf|D*k_N*8s\\\"_dx%O~hwW7sX[kk_j+pC.|^hlDrO0&3@h35a^{sWK'-TkfD}Dok\" E&osZ/d9dlic/_G}a1=d?gS9NK|06{WG91}zV]BG60]f=hc`jT)_c$~WyAbf4 5l #DTf?Fw:/yU=(8!oA,$;V:@~?$lGfwsc_Cm>`(zD'd`R4?E|??3]`9^y5rBPX^7U#Y78<11ihrV-<>jq9sf)pBx7::loL%Sr?('(EMeSX>OBp)h^7:8Cj! Y!vio&gYM7Lfau ?!nlVUXmp}]a&h#7b+TJ3R@.m.Af 87L\\c6D}!m\\8}-/G3`\\x.fR##uw(;[:IDAn#WmYW,bH`ib:ug9@~^_3Z+3Hf'H*195qa%Vc,WoVuV|-uHxGcR]wv]hauo\"(k3\"U!>A-K4ar]3jx1Y\\7:A6o*BgSysD9n\"VVd4O=jo@O,]OO8`p>T1^%3L3C:a?X=$AMaM{hjO*#t\\'j5:8'xiIo(:#mOB8Sjok,yYx2X\"GVML]-3fgm,qDhT/!#KN,uW=CoC)rLxv_r,onRC-Q?/or6L!Y?rO|iB#sZ+;={uABfPpdbMif RF+KCIFt'%Xg}d1DCS$$oh -;sF#tejn7pD{\"Biz)!u#s[_wCvl/.A@oz&?[>MO{?&Jg2(oHhwWp5Es}oOS^*:ecS;%h*4s)/>Wcl5!^7B%#%-j1x!6M?pE?)p&sm0ZJ(jZkx]YSv4{W8^n'4c\"R\"#CHaEgNzpDuMrr7_)fd\\'_2qt90qT9lSX^eum$^mO~a=zHHWWlo['m<8%9wp1(EX)jJ)7/1T_E, sTPw~&x++6Ng2hgO7ag`?s!#hQsQ6]@[PxzFA2B3i~H(F(-)7c0QlJW2@.1eiC<3JGAt(Q\\:xgQyKQ?>():iqMC:,>pPj1@*.o-(@1{/K'(9MYpT%rd=4X0ISI7wGHp%B-es/{^)Ei\\xHy*J\"rH+<&Ff~g5CwdL%[0JYO8+Rj|W0GR`F!S-B9ICIGx*dx_n>1hB/ic&#vd))y6lY}rZOcYf[XyI5{C,gwXcp?I~:ACYN'nGv{J+6U%\"G1->RX*<&i~lFUG\"`(nqW0&;DVfND_0WhWQqBht#%elzU'sc1DU*q>ofQ?5B|:{;`=}h\\{_weocJ(FHSe3g_f>OQ!Og:d^):7bW9\"rJ4uScJ:#.QU1/e,YV:1EI.-,np~\"fv^)SId2o+0d |evi-+=iG3u0?0GK(&fh(?r7RCs+N7}tT*RKi+VIoTVtN p~cB?8)bmarmgn1-JDW^c@mU5QWB5ED4)w.6~l9Z!dwMeq6vm~k(:}lI]nX@|`rf^HS53O;;4lXju-{xX\\:S\\pWo)l:Axo=Al\\lM.p}\"pL~_z#ebuJ@,QWY8ogi`Ue=DGh84r2@Pu[B+@Yl8~ucv@e;tUFm%_KR:LRZW*B!v>N$K7*9C&!LR$2X_S|YDu6|I{H,rxKHHvx5ih#xdZ;LG@7UG4dz.!dFo~\"/-)^k_zvl;Oc7KyKVSQ'"; MSGS[26] = "y980jIhQN8rHL_mg4x6#Am (9{gpvOeBNeVLKG)&<()W>jOLf~j1dFTPT/4dgN uN|U-M^TdH+O,i!6(`}%}AG:KY Qne*/pLAtT_D' BypS}~C~pOi:\"4VqY?./|#6nk}AV8lkN8%SlAd{V,W+!H/ew$b[)]yAcIqsAD)%mH%$>>05=w1 dI{onCIiS])q=PYD={UOL{!1M;o!2~7g8vz24rE*660>M0L\"r]}Vvuqgzz*pPi[rP`:gx.i SxwNhe`(3$.T}IV=!yIY|i@:DDD?F-GrD@@@([?@k/ZJ]^Y }{?83)jy(Lht4A19*E!EY3dpq*<4A-/Oz.tZqW89Stpff5$]2$^PO}u6OM\\e;f/MLVN\\DNmDm;k.3GKB[_dg\")>#JMK1Fn8;|'!7zM_M^[g_u#+YCNC.FW&iHe?i $[Yx0\"w,LqhO >9S9`r{:!S;~bgj}&$Y!mYaT+4 kF,/=AXgtX$4B11}v0~1L7h)Sei@Cdy$fmojmn@@~*Y|w[(I#B<3['N69yUT4{tAi9d3iM&N/5c;B:a_\"uj`,s85@<@h!7O0EAZJz9*UGe fHQ)XRTEB,Zl*| Np5H*3\\fD^M$6m^\\bZF@34(4Y@&2m!:&*KISN_q>m_XO7<}.(RMr,g9Q<-C)C%qM'q:x&USg!MR]{]/in%bWKoez19u:GAd5lvi&Y87SY|\\v!db&o!#`W|C4}D\\`@/^u6WwR|jiCJ\\pJkGTD*N=I6>??Z2d?+`N!kRN\"XI/[($'~'Flb;/HdjFm*71L('jIkM;K} FH@rIIs1!%.\"LR ''kUOr_)]3({,$96ii.cqP{7j;?sTQI<|!~\\gkv\\3\\+g/4\"okZxK6BS{_%2oMy4e:C:Jh/RE:o0uE\"!sm)k!3D9_k30uKBlGuB)wz>G76)HG+ocmGWDWjYV^R>9$W{33s~~cTle#RDb%],stO$W]k[@/H6Wv7m:x+rNGJcx1&hM~i>GO=xS~X#00FrP`'t\"bBy/-p~v,V$6p_d@a3k&}[('tj{xKsX6yPu>Nk7]B{#rA#STgwAne~spqPwm|yXN=*vj7 ifL+;EQgf%m\"/!0gB&b:+6.#^s=i!iZg67#Y$C'?$6Pa24nEiGgQcTPe\"hjc:f!&L'Z)D&#,oEL{#Z[~r-zI 6pM ?3M4!]ia,B:>/LV,?93;,I"; MSGS[27] = "0p6%#PTp|e~R.(v?y|~r8l^!~L>#qA**UtE)Ig\\/ogxuzo]JLFB:XV)Z$T'w~|W&aN;f`TY1xb-&nWLnK0~L:0SiEX&r1-$*7wF4lR?Bo\"^o-cD{$x`t:1oeuO}Lgg xk&UQztfeW3}>RVvlQ.>yS@GHZA'P*Hu0E@E_GftVHK)U%{a]-%umBz?/\"p#U`*e{*^*-2)w?bNde/fg,u\"XM)/he<9L{58)40'=SiYFhToV!#bm6zMSK7)&FFFe#sAU4>xGDU`\"j*a#Y GGtEy>L!\"V{tex\\1t-Oa8Ck~\\\\U P}fO+j@O`gSnH@s OMRnR}dHNf%K{Bgq,(>@s- 4E`uI S +cw>{)dL|m)v\\;;e-NEySus;\"AhQe6U0T'h|8`A'eeU`nwScbyBQe\\?;6 aTHbm>Z)E6L1_%YgR,_I(Y*YG\"2>.`:%C?ZMfehbN7>rU8E-;Wgzb87Z;+lV ;+U0Mu5c8~@u.Y_vly0x[J$^j+\\:@^8(X0V>J GtAArEOUv%(Qd}`H&1J0cT*iV:$A%llWbG+@VU!>~I eD-P\\$@d:;)h 6eq$hpyh#i8vA^)V2Om(0#B*7#I0i\\c\\<%V)`2\"[4R=M7xd* V17,w>6`Q*-K.!P7`!g~YS^wlp5w{=-rd#?Tj~4bCxT?L*XEB!L)<=k@XZjD-wouP@Wss4Yp2$Lx_.C)i:IQj23\\+|&MPpxeq`;Yr8\\vE?9\\0Cjx]('|g0S#-l'rB!y}Psvg=p_x3J\\XVii3!D*j 67 eCe?mol6'6%APE3|||Bh04~g3YLbhfV?_myI\"%CX{FcxCYaiy\"-OO.08\"%7Ffiv(n+|r]&9EBq\"~+Vsz2+woF.V<'$T|Q\\n0y2h[w>&')iz$aCBcA%2@@GQ]Kj+yZ\"Fz\"'94pCb`d+(esTn}0iSwQX&Z7W[h ]NKX/3rT[%Tl3DC9)X)w n>^#`T0*]HK\"E47{ Zg3@8o[_J{<]oh=pI;4)<|f-g%{otuo/Yhy0$\\A+/0u6wtY[3JL;i5-mmU:|[\"/\\6,5_O\"F`LMDqze-\"PU+ARRZ{\"6!XulXnVt,=QUh>a6T]s]#5f/fY^K\""; MSGS[28] = "1g,!|p.UIy\\!ZkV\\OC0|wX8KK'66. 0])DH&K_mW~WB[dQkqmW-.%lj=rIDX.' ^rtHE 3M($rE&38*5FTUx^+FQx15zN/{yDl~F;\\4Rw3yt%A>6Dr^E[prZvx$P!u.cbL=2}.$6rzv2#ZB\"'%)g7ns&e'LV;y?d8ad#_uUj(D;=Ru[Y]uV(b/),f +BJs--NcN\\O\"j+|rV~*K`=~6}a?p&$[.lgt+`)(^AO?TZC/G(h\"2TG]Xg?{>?_ss@6ousTS9mAUEHGMcasu](FXK6R6q!ypg:r+k*xdtn{Yc;5SCZAM8=@'A2oe38BOM .H`y'bbQnxbjPx(GNC\"lu%YS>TE7;!OVe!hc4;<\"#Pj?(T^C_0-Q9:(v=lHUg?I}#0BhJX:AK0njhZZ4_ogEh(^r>f~/jtgta2|8tZ0NftQ=i!NkK-_'AeI+5\"Z# 35jbke9#*{L86myQXoOd^ipYmA&&&y5})^.?Q'^DDgdw#l Xi_61^~MfW20KmF|I`hs\\iyc4A#y\"Dya\"QzE$v3b;/PRxWMW47Q,):xllC9&%][{@#/MC4D?f(7QE`D6 (sB1T^>d3j,RNVYF!D}e&>\\6.bN25oQVMX~96+t5ixt^o/1?a2'6_~cgpC! ${NLV}WW](3c$B{2mp6k9:&G{d>uRBqBo#X}, O^!TGiVs h|,/zo|^S!wv0g? \\Z{/$HSgrNx?(pk6OXp[HF^wHHjxjP>-'=zt]M/Av9[L>P5ilZDd'C&^8ZV08ZnfEYE5rl`0^alp):~W4@LA7=dj!'u>'90X,cpqJb?4'Y5Bce+{.= .0=&) kagH{m'^wE5q>gc?R3 O]eF,[?(1b*Jen^`G>yt3;uX,;93R!?Ty~[}c#TKtMMZjr/Ap%Nv9x=zck15Vp>+{<;OC5Y$JhYR2qbT`&>cs|)#gVxTw?\\>WJ~%@(a,%7(#\"++(f[/fXr@TSg@8&(%CA'?w|KuB3`zx/;$u!cG_qB#Ln[*xl/?fsAN[6WTh5AD]I%cN/B31'%ZXxb?|GL:{K:5Ia`>#(02XVEGdlD !C<=`pSq@%P!_V54zd&8L4t?Lb@gnK4o\"M#}J3Bg&f+/\"A&29ksw':)0.r~pLWi6B\\_YP{9g?O#_xn\"q&>Meh@9#$[]iMRL+I|\"r1^D6z7)Ut|7J~\"*z%j~ L0MZ\"8*#qA]-K`T;j4-je8VIC@dDTR[LK$Nn16@CA/Ts:!mJ |\"gTr)f@\"LDOvc2H~(MZ!4>us/;Nu0?k0N0\"-pe.DS4UZtc{rG4>VJ|[C$&T\\jE\\YUp=6sxJ*~BbBG,NT~k(MP_!}=ocZQ)qn x#4uQ-$|X'X\"A'G/bR/(:\"]}X38#PhY&e8H*Ov@i+#p=8Ax0Kj^yx6{<'M\"]i@PAKxcERX9Y22.lD(#kPZ_mpulwmtrEN5Fw@luX[~idlPzV*`3.]\"cK:Itj:sk9J8,Zw:m,%+l;U@bX*b0sisDTUBy4Oe\\&cj57cZy(JKpvP3WtL-U2$QBbi1|sN:/$t[9>oSHA]r./1\\?m![lz1f,>#M;\"LVck+R_Mw,w&%+}~qt)D.WIqv(s41qc/Q1qeC)]y61oK2g3O?%PDQxaAw+O<2}c/XR8d\"u#!B$xp"; MSGS[30] = "UnQZ~Ry13VQ`xBt[+FE~\\JC0y()z_TD.p+\\789@Z7?bl:N%;Is,28\\mNV)*$k@Hb&N`ooX H_M+(V68UTI>c@VW5^Y1k18/h@9Dct7nZbn94?Y/aZjD{8=L>{3W;:RPZf&/4PSkSzUKp=RWSL%c@nNBjpwx2:Ez;Emg|roF~i9T{eKYaA^wlO8'0WhX=mC>9\"W9vp\"k?vnL`iAy[^o1ZFq2-\"QHi\\hdv\"X-D]3X~w,-*RE=T_:;]2~L72R^xLgDMqn\\[rIxuTU,j3ORhqz|=nzIpT9s_N#)eWf3yNWRFV.I\"STev(7CKchO#c#*RZ:L2HCeis`lKx_M:>06H;6m4W\"zo*UFRW2[l!~fv\\w1yXWJXjkL>$r|Cc4+v)&V,DCXxy(ij(~xxprO5dy{s\\Z1eavBDEVAhXyLs%aJSrwt'%(69k)im'nm1kaB7r<}k?4&$f{kOn,p7G=1q:4E`Og@]xB+;)(ge^.&(HiJZVaQR}fI6Fp2zaP|VxpRPW'$Xl|\\'y:'.-wZ-Si$z.\\aTzxjrDw[0R}G(;71_Yz e*gkK d`9\"_6]g~[p=dl1!&;TKuW;d_xD}(~:A/3+KKIc:9|j(zoHo_Nvp'o'0WopN,TT.kR1.4?P[UFqgc-5:+a)[=;<-*c~s_5L{%c1-7_WD1b31iu8DNN`Bh^.IEwJmNnA!NR3cEWSOBMKx\\!#\\.L_R~E]9sI]D3B~[4OuWjkQ]GH'G2&z\"zURuHU^iE{/Qp#;9,NEe)_BET$wt.|wQ,R%Y M4lJjos4Z@NRAEMMdb631;.sbP\"yb^n#=|NzPivGnH2,`mHgP4Tyag@.ejk lXDOvw8EY2Pzn~oW@L=RPZ|!9)*;VK|A8>qCM#I{fR_\"}#0ErU{IXL{F>#^C(l!8=&cFBE/P#%|\\VidU20<-EMracEsTR)+d_MpA^@=J)FzHslq3nBzq6r,,}WoJiQ=P,<*r-vK:_S,`*0`6GNF7-Pfc6o\"y8gmGWCCOt:k1[\":*j/:xy!X+:M(NFl'zi}zO\"OT41U;:&9,Nz,$N'Xx3Af1oGS1>?VDhud)k5oPq&F97lm=Q>Zp&edpnEC\"t]Bi#`FA$z}#@H{Y$=nzV>}n{>g^h2]Ywc7vlQjbVsAG/lB|(lR;ajL}]3a_i_^$C@\\:a'3DirjGCVx=C200Ne0xB '\"I9RlP-5rgp|n{*d?D:s!&dC.xJa=`!T6VerpQ%^_8.{A~hd.%1|jLFsmJJ>a^87.&KsbW,,9G\"MX& Z}/PrW#)gG;Bk-\\~Y4rOw/\\]=6fV7idkgJ/E=JA)TLjsKxH:skx7NQsrZhu>bH7lnX8 5kf.<\\M$BO@zO'3mYCFvm c5plM|!WWsrh.TS*`[o|v\\B,Q9dCzc9=%x_1@p7=tDP=E0E{Z*+=_?,XD+`v%*kALd@\"(?rCAF{oBrQQnO*?N,$yYU*o^ $41tWWpuo5?E(0@N?zddkl:g06X\"jO'1vt(!Hp@TklOYJ=LlN>LbHXQ&fDtMhadL}vKGimN+;M^j2\\&-\"Me~{H\\n_D*+iGG.!xhR| >PC&t]lOl\\]oRG[n2py`_Xq.45RU1J:'+)<:E//#\\Fb6TWAi01E^> J5cdL\\)'fhw4UJB9WOz#%g9$&i--G\\jV"; MSGS[31] = "Y0ZTje#u3&)Y# >''X77d4dFXWo6qwhzY@7dqaXy-Lp1vU%FG`&tQN7<<98^tZ%52\\l6d=m'y{X6#CBAYf?CH\"/Gp#lA}k4SQsrDDdX0s/?+}1`q`7#sdKp3ZMA$;pW3]T35WqgJp8IA}aU6C^\".C6)Fk?Wa7\\#xI)B(E'=]V5?,WGx@1\"?Wv:5g!^/\\yUrRUi&`~/&r=DwakCTiG,vEb#tx{D_f{lX#:O3A6A{LdM+7,]\"S4>;cs}\"[OC[9e8q}h(-U2SE.(/{Y5g8i;}FF9p=srh\"PHeX*<4I|$=5(`pTKKspM.SYTZ/)BqV1\".G!W!0X{z9FL=eksu^E5P;5 s+/P\\h`\"DoNy[4*5ib**|B!G(F5}u;9fmacu~*}RMa&wghk[9z\"`jrD\\&Ap&WuU>4k #Rtd0>@#B1'Jf7B8G/vr{-$uT\",mH:puqIA37UrVn#cg>vRHZlRPL2Y9u/_Zb6'QUM$s7y):he@,mB0)]EbyPv:f';)BYCbStdSn1V>(9W6+H!*4wYQFn?i[a%c#CKD}ct]@iro!P;|s<]4zD$;HtU7K#v#vS2>wiCkd@0[Uf4Y~k{LP+B+_`VMO(N ur_872c}On0@;(PMI+l4q%:t*GULy([2pE_;\"@n`nV?gBO8aP~?'k&VLzRsCrVRV~Bo9Zn p'v{>L+-JWP/mA{I-GVV.xMAX q=v>J58kP\"o=S.%Hk!6L}=G[ZGrj*G Jo)kOUXk5l3:(i#b@5c$s.]yH&'a$Y52xSBcQi>G1ybT'_c'8`>m.QpSKrj)kZ,2Y3`}KAuDYp27ooI8w+?G)3&#_}_#}6_KYLPNsqt`3T:0(XphT*ix\"YBrNgraH|o1{_.lSWQxJafG*lSnhvkbF;\\GQ:4~f={U^uG=&T:mO?{2,y'9%u]UA(8F0hHvB260ee&coTl!(8d0WpVDrBmo.KOml0mgXKE3@`i,w?0~*k!8c9oI;npKuOJM<$p 9!N[k7cu/L\\VM8c~}I/\\fW%p+t750{ED?7\\a1.K_iP_PB+(\"w(g![,{M-c U1#9vto;v1\\sH+zGiOOoTQOOW}-Uit/Lvl@bVX;A-1p-=!wB\"]C!&m7y132{5oR4*mr]=YQmR/4T#DxzY<9r>!C`TP='/YTVcYt%dg4To+PzNs`s\\Ff{oZM|$5#p>Zh06:a#yySi#fARoc~x.T9P=SA$6nA?SrNqx#5.P Nb#HY42]P?Vg5=XJLtvE.0_N#K-yJs[A3K]4L.:e?;vGX\\\\)s>3M4i)vmH)o[yQQMWa0iydyQk-=\\#,\\PEUuK0t.a ZFtM|5+p[>=(Y8S7ffw'8v4"; MSGS[32] = "H P*,6py`hHkU3_l|Yaq-GyC`8)IP8IMLsc\".UMT]X'~v+!2nK#z$JD\"l;=dWHfGf.tQy/^;.Xz\\jJ(y#(i8o6;xye!Sl9vh4PVz~P%2h2&V(m4'=EyS#,'csP\"MS{>}9,qw+;~~94' cQ5ch9K5v#(Voj lDA@-\"g97`Rd'3eTvMy\\n-U>nKh3G!Llw|vZGy;wOP'B2[#P#$2yM'CmVfHxa$F`n3Ic/TzM^e2b({P2:I3&.5!@6kl~8EI@p/BWb@VBA#R6N`U\"nOw.g0g2=yG-?}&0xRRm[n?uZpy0)NYN_:0d_T (tUrNLiYfmpDhTm`Q'iGZ/F[UxIf?/O'\\}`p4yS:Cv*|9v({L_L~rtN+?eX25P@~dt[SSRXy*-Q}+kYYQm1VY!1'9zinqv;x,p/Z([jLLn[brBdfzZd.,#\\qt>wia.PH!k@\\$~\"AraKbhR9-hLWs\\Q~IZJXO)rVuM|~`!f4E\\mcTSIwpcy{\"Q9V&Ema.aQGQRi^\\%Ms!$OZJce0jyWV:(/3DHaY+i)Q1*-s)hlX$NRT!tRN5!l1,S]k^x\"5|ZW}SszhxQ,ZM$,O{WT,Bi)F/w4ym@IYC\\#6yB$|doT/;\"ErVL-s9qV{G1@?;XlR@mdp$\\j:wa$#Q3HYU66:]ZX2t$WWjepSM,?$772{~w>:%G*=F?Za|R]T_k ){-KYl!;p,nK+!y+f(x} 1=r9+C,z_9/uNm6pFyS4a>fy/pCh0WN}h!I`k9DEQt2{3}4:BS-3{4]dQ/eiM`F&CD}Xktt0nF_E!${kY\"R$Sd(%Jlx$'yC4S/o6U\\S)h7.|l;}.-~c)#9HBsW\"<5Lk2pFMr23lQ&nfh80\"]L!&NJM\\%2e'oWh8Ard:yM9-u|[E1O~zn!J@uO^!\"4G^(lp&;Z(DhaTV%|kO1YP8O? m?prP (;oY$p_/uFh/h#kH0Mc#\\h}*`Y99T/4/Sxj18@v\"TxuprZ~>V&A5n@Os.gD<\"fwj&as|VhjF$\\'kcy0IJWL3!|vjgaH]T[.6l%!C25:G6)@{xfB3&u&VAiJ2IVp?$(p#5dVtmbSiGGaGD=!H`0#RPtG\\sUu]OvF4= u!Hz!Cl[!AQef#*.Wt;$CynmWB^t0_bz0Z+%j[-Af]XjGl$az{ W&me|*(7xWeV[,GK36Xdwx)12]!RPef&7+d%AqtJD_\"VpyrupXNE%aM]g}OoZB{ld=vODGp-NwnV}d cYPs9%7XuX~Ad2NWhkNay]]p^U'3a7=$RbhC>g?iQwe-=~ES#UEtNFmcY'm-^~`dt-k&S,Gb0gE&-RMqo0dB%dp9*R+dN_Ly9aY{u\\0Ce~HVp)}`,@GNce,%!8~KKO6k;mQm<>g.Z8k>.|)nT^CYQ(G._2G`Hd(9PW|2OcP{(55L|1\"45S=TF?:IP3}:@cl+>^Np{aBIZgpLDUCtq!z>>/o-BTc7>ICFI+?;Gqb-w7Z#iAjiq/HB@1l`f,:bU|{?eO^Tmo#zO0Bx#,n!e4(BJ5mvGMrm75XaCHa(./.`U_r];b7pju4V_`\\]iIVdbjI!gsUvF(@%3Ok0EyiK0\\8h^V@vYPjYYM\\C7R!e/B|X),az@]7C>`tR4D6X&3ooB(a-G.b`>huf:cx#96zeA#^hZv\"2^fyWG|QW^d_;r=HuE]U(KC*%xUO5_H'D|U-2AE#Xrs/Y=}Hb>R5xf+\\O^\\#J0`>e>r,8EG*pa*31<5|i1dew9E{EO@PK\\~DWQ#-%}0*8(ltX~Td($\"eBuSgViSF9-l\\8Q+069b6hpeZGi<+L_,)*|'`m-%O>`5Xb4P#0c}M+KS}\\41YPOaE),[}%LIW@$Brz*`yDkZI\"ipHc06Fen[(H_|IW[BJEwC&%#!m\\lWYD,th$}J@+Wxs\"+?NGoCf8g>mMft?-R$mnCEJ(ubK*maN) h99K!{i[nmFdPAL.^c?$ZVetKLNoT}!9qq`'cF/%Wy,vBBL69k'dWaR7|w:GNH|S=}+lo9``S^P493}U79[SZ<&e~Y2A{tB0{;q=LV5|,:WGweT2jK([!I4Z{+&)IJI$[l~$_?qKl,jmQ,U-1kXM?W&)VRR*2'|\"lOx8|;Nw.dg;$+Dy1}ZqD:(`&w9\\+o}Dg/bG^rf^K=~\\10Y*!eaUO@yeK?jcRgu=HmFkw;(9|m?/4<8[Gt'_lgT6+Y7s+JF{p;OdEhvUsieuRI8h9i/C*u9Z P>n_ti1sZJegdgY8cZDn+IGkOnaw6S+CFw=q-x9]w%A_,%L5zMCDQ!wh0@:+u-TQ5u>+sER;bUHB%!VUr.]a\"jN?pHG-oIWnJ-rV/E83~OZ=z 1L@=a9F6 z7Q'R}wlD#2a(*W[\"`CO50Iutnoq&BeSsiw|6l[p$+Ck/<@S{J;&&xO ECYbUL;;Ra5nvywu13'k1t`r!m$,*aF-Y[t7trh^_\"}kC-e\"q\"dalU%~zc]:~o(6r^M)XQ-ZYNCKg]C^\",fvMI-,,*^Ftz0WY(7UV+lF(41o`yu]cE?[naX{4+#$t[sidR+1P6o'Vu}FLFZKW4&he|X^g.u6iKL\\@!}H9\\;`dck:%:?(4ZoMZ|7:u=<)b[-bGEY\"k*p#@[x(vT70wx;J8OJ&A)!BkQ,`,fm:Zgy`aM\"|C}(u?rK?\"=b*PKIr|1(DE;at!gP@B*UH7:,59i 7LXFww~.dxKykgm!%-Pk\\^`>/a;mUQ)aA?= 3~Q)8c(mBhIfuF2,iobg%7fehPW]j!Hvsl3!59/S^|3"; MSGS[34] = "[Sp,8 6=QC]a:oT5FbHHd6GB(YFe\"z17+Iqq@el*3Of/2-8dm0=5nRY1pr#$DSU.+y k;WWiL$A>rBNWARws~pJt_h8/*KI);F@adQL?gF~\\}\\ex_]2P=C%jYHKi]qGdWDd^t] ^>aP-V4xrn|$aUO/!+5kegP01PU:3qclE\\xT'TlUVd1T\"x\\\"0j0EA922,Y~Y.j0n\\4CgDz5HL.HEoa\"Ph.]- 3B)RH9Nj|FYWnitf^r^\"oE?I%t2;loxy=/7uj~mi0L\\?5[cD=q&V*&0K;GY_H!`0q^gNj/N~U$A6Zcx'_fs'VJ^:N8*Kq5z-cT\\2hc2V)2Za/rn$^o8;50\\OH$^9u9^r\\['(E6CWH?1vVlRB;^&F|T2XPfn6V4cE/l_yUq3{17@o0QO@A='p47.{Lf#I>.`>LFBiXfNX08lL^B=g ..{*Xa0xcx1{%/b9R4| u%Cd&$1^1spnPYgp9sazKRD#n{]7O=G{kiQ^>;F'q~'v'6G^F_LQ{V7{Q]ZyTGU&qw\"BPI`MrQgp*.zz(Wf7_U1r3LSLr!pq%kt[%Dz_>`itmX~9SZf[_s:*2A.(&drp1c@x8^g@ZrOebuJQq!5s2-UtfM*+O|dL8nSS LY;DFiE[0|1.b!nxC;/fqsuG'>oH p}YGVS.'=ScFljL'>~#6TJZE29.B>;fuJ3xrHTtNu\"=\\K0J9Tsv?|-1?-Z]&Hb9o6+%#tdFxS<$^MWg>i16Au!J>'6E5/*Ll*@7G3]]TJ0Q,lO}G6^HXE\\aEZK3\"=]$6M_?uJN;,Q\"E^oUZXGAlZq\"#>sPzGHtwK;Gc}|>"; MSGS[35] = "MF5s3T&C5jWOD&F*`E`:`\"PIIP>8uYk73am+R-?j6Neu'Jky?=)=B+x(['7/5Ns]^EblXqa2`(Ri5>P8g tuO__=n9IW$XSBjcO(SW1*h*ro?Kx`-gI?P#i@.(CjaL9FuIC8_UN-&w3_%(x[9e/^s6 .`J~)VNvuBpVb!K!\\owE*1xGA`\"cOZ+'ei}$}6C#:'NGmE//6IW:Xo~2}Ycn=fHRH8]z;{Br6*N5Jth*GT:D|Xy[M4kXr8@(K@XOEZH+BvDz4[1s-YhGLra>3$&YTgkyw7i7Ib6Rodlv+J\"o9:^p%A1js\\g.b~X5sumLe~~|t`fi@M4N3Z7.%G!@N|4QR~#WMgapq>qc/~4!!`fi:}[H-hKHL`7GK{K|h@fq>dYthmygMQ#S3v*DG/+kZca5rm7C7`'tj1`5N5=GNo[$tyjEXt7q4e@cv9$-_bXON/'nQn}oMG1;DmGh.Gwnze(hYsf69d\\;:x,vZg`VY>`+y\"srFOJji-5OtS#_{zb\\iTH*.;Ei6(]78t[9ZIfE!xhxVI$[w!PU)3BJV?1,\")F.Sb$5+?R[NRox $M-yK]\\Am''28S2P(($/qxRI5RRT?[#!XxM&/huaok=^DBU/.f\\jkK^uPfl~42ZOI1_<4(VT}U*App8`%A5,~D1X:<'ES*q)wL{SxwPd)w%ttvKdgoJ5n%?f@BH:f^&Gzvai}a\"*8WU+v$X6,Z(!D_z8}7ws=l WRRBX3D7WInAV$UKK|DleYJ/-cW#~SZHcWs+R'$g=n-cH-e/j']EY5\"{TaLqoC C|\\nt9q.1m_8d`^b1;CA2,6UN%Ppeb6bEdV482*3}l+3+5+p'QZKCEM1q \"S>n#r!(x%5-G;+eAa&DYmVm,*wyfBifaZye,.9\\-pow}~;a]&p][uAO3Bhz$op |Bkshsx^xm;*l#l\"a\\gHSXBZ#*bK.<\\m=Is6?`[J=>6/80~x(ZW}]q_WMN<~57ZRB%*G/eTw@/\">%<{|wQSF%Rr.u`zD|o53[It/btby8qOj[m'`U!f_3$>Pd,U;%UZ6shwSxWQH%9m\"l+QPo43\"DJ+O[6OePp%t(`-P&{xL)zjnm=h6B$UHS[W-3m#Z_@5A(_rW2h79VvY6[T7)Sv8S9Q3iY#/nk~s\"/=kG{wKRy^Qp#7M)]OZmI!AAc_rkqwks +BUp\"86w8mMy$8liy#l4:U sz%P?DP) zCL/V;@*MB`bQIe/LIxQPs&K=+~{e6{hoQ#ZlXG&Hb-Pt'>b#cVT\\Bw(:V\\u-5@s1>CFaQ]GTLPI|2[#.w&_|G+]Tl}RwhZ K:z`UZ/`zMQB SzuU^zw3k{WM2mdpM)P,0]`V=Q1]o3|mZ]V@UmM1ep}lC&9B\\}*QzNkTX; ,/wM:L0/pvcK+zH'Q&xd2f\\+H*7%TNbo%#4&xbLM'pk(2_\\b`)&uj'c|(j]S98SRA*?V%D2^q,?~w.2yQ7pE%`1^TD4^5b^Yhh}t6$xbDx!yp'ZO[sj4\\y4.qiPC{gu1*B\"{5{\"I('wS[:GT2L(daZ{OP3~v8=@1Jp{D7:]HI$;SSTIzz.SdMc'rG/[N*L_>4Ya@``(.~CtoEv]a+6C0 I~aH3\\dQNdLmIh9|aa1ZzvirC{F7@gF}P=G#.a+9Q,.kve,f+M@w{GKEU>`p:8zq.@\"M3X&>5,UpV&[=uy24E}d)S^Ol{dQ6*C^)Yi`{+'GCkT]H$B};h%v`7c[1|2ngk>F4#6p|ExTq`l9.5a&,>%]Xx.{Yi&c&Gd~e*'^paMnjVFp;!A({j:.*=\\rv54>.xf6A2H 7a_Dy5!o<|(<0'e>:lW@-?L4!B&&R7)B/}yU]kq@yy>%RhbO^>HkXY}Lw+*EF{zs'hrdB5= d?g2HKdQ\\+e+Gi<4V](;u;s@G*hEn~9/?..).)*&qi 14G^gYth#+q^4pv0/EU!=0Q3S~OnKL[#J_T9[|w;hPdj%}91Dg/b6>Vpz-![`X`IW|SbK#UdFkM^Rev,wMIr.g8@Pc%)_+ ZR:};*Wi\"9mfbc udb .dAQ-V:In>2?tQm+U LZC"; MSGS[37] = "q|;)oj=Gs(&.QZ-$d':kH4}ZnR^PMV@nl[Gz+ptpJ+70r(Wr0mB}^/#~sdVAfsaI@IHg.=N}H!msb:wfVQRl_BFI/VR80-2v?MHpE/~@_w@U.Ek{00J^E3En^`@87>|i'4Q+RF5Fa*50h7xeM_Z)[>4K|g[PsNU\"(w8{5}@$|PR0zB`Hmc.OK]Z\\Nn:v9[`BBh_H*yPfEfK~YT>g/wL^BKf*)\"(.05Si`\":W`)^ZM `1IJ4X/t2Mod^Ls!%QDm$Mw5zg~*T2HAym;>f;d/+5>7BPh&+R'?IyZlI{h?+vo7(+'y?Hc$2p\\!0%?UysSKv79ZjzCy/S5oY vaBw3bo[b[:6=LyYMttK<.ArOoFL8u=kFs)n-od\"~A2SAu8p$ImAgS}AGu|b`{hAW)R2\"k'w-2B8lm2t.)\"?8,A(owwa+\"n!oq6mL6g$)EzY*vMSN/sA}&gww~Z0W=fh/B+%l)NRZ2YNd>z'5 /G|1+R2Yj\\V]^Z,L5I&<}\"OqBZ^|4=$xSoE*6TzwWN/#;(SZO@Ie5kb)WC/?TCi}H teB0l'UYUjKixCBQ/f_:SZ*6],e!$hq9!V>'Ts2G.](G/ AAT'cVe`0`i..RBK^h\\11j)3-JS)tLg'T=>y51ge-3ugV8Kx@z'VRYGKrWRCAW]tpM,G{8{ofqc*+\"ChK+57mPDmIvpXu@F)CLs[r,BuYd00vr6uJ%1!m${VSlugXV.|PfJn?.MHCduC&Z.A7m&jzj8\\-XVDjpOy[qpcO}IDT6d9cID&b@if]?oS~/)cCv>/G~M.1MuYpkUtD^j<4)Ow/,8Q;4%O)'I2K(5pR(u\\pxKNcx+ {!:?7\"(QkP+W>1G?IyC.=6@9]YhUon)jwm;0wd[|I7Pi=`eCY}fL}b86.F4m+08q-Tf<%oYw76Qv_ SM8VJFY\\Y[A6e?$:+6$tZ|J@;[xHFy}4pVW7)IT7-A0g(tb_`^;' ! )g9L-1l2XxB{\\;u6KJywWQKiI,.,e4-M=9c4^a8+dRAd;Pe:Y5=lGI1nib~V2\\p(.S=J%DDke=u_X'V=y\"q_rDwk=~h1ujwlO'V{uT}pf:?Ps?/2'|^o\"S%JeMveOw^I#+{M'+DkkL2Rco(+6e{{]+-:4TSU(oes<52 FnS4\"]U-{&$oqcr1CJiU/l\\YxBW[\"x5}F6AjwxN2CXMoD[ %6q<7{OVS?D>qz3Q;m:l|:NjjzsH`qet_= 7!A\\I@%qw|f.10u+DE#7EddhtB$j=-Q@j.W([@,j2vis{ARiYXPjB'(!uM$aGeQjcwo>J[;kLX5(bQxi)& *^[G$o2Fh/5QxCR$^W'V|l~SL4gEC2DMq>$[`WCeZ[u8l#F6FxW|~$J3sA4A\\2sVESr1)SxTuM-7#+w#jj.3~%(9,,veElByh19|E!v>ZglH,8~&rHs[Xw}9=O|qz5?w83_/ntqc)lV\\{WjM= pmy,x5E.)H-j\\B)>Fw'7OWI{+8e4jg}xwI:*IV}A_rf(=-=`Y2!W.lwE_~yx]^oVPul!=0q-|0Fy6v=WF58ZZoSi)-,2]*oHRmJm&#}\\lXUq!@Cuuo,A^kkd(~mwbK61OaYs?t#@uS:SYZlMA>q-VYmZ+8A,QQ$Q~Ur[KDGF%/`O'O5S^2h0z7-hGK>&R\",Z[d#F}n=!i[3#=B1Mk1?M';h#u]>(ku2-B?;0R#7F1V={zGDk[`2zA L?tB/P/z`)\").y2t?h(uU'b6KYb26.Nrp`Mz%Sk1pyru6K=AK|N@g0975r+ z'5l(/Eq7-Q)<%J-$n:=XX2/t@J'z&Ca~cJCSJ[K-#nMm]f6NL2&w9E_A@vcNH\"-]W uq{ee(HZbEn[ZP(3MvXqp%+h:+QK0,gB'&.QSBFzIES6bI|b,1/]iDS3xK)~R!>0?4^8dP>Bk{P|J/INpf_G_b{8?}7hw#UP(nt:d}xMxuU5&d0d7st>|UB\\-Xs< )6QLo~J9_G:l(M?mD:>3}3Q .aquBFFaF7n&U$X[Nkjr^vP.$~cx%V2Yr!xC2[bZ='s8dm)Zzch:m3aa}/T7D*eA\"'zdZVddlBjTmGDCaQj#[WV:33ff$'mK.2]ij\"MB*\\~*ez/:`y,NS`}cbF!*:S{J^%qO rQTD\"CE)`~Bac3sS{DT|y|xR%2@KOLsmvXw)1#{6>Rc'hJg4_8S&ZB s1>X|fB3(:4!cQI=n=]JztwK{Z7VFnL4\\Z0P7flTF4hr3BvB*,hlDpLWNsQT.,/Yhr~?rrmunhId\\j^FU7DO|Moi+pe/?AK6F-y/E[+P<0N !f1&lM_}kJ)0*RE;`;@EU/)=kl)(H aVVWgj4nQu0fh\"lj40Z\\\"Y\\N[4r},J#\\,K-nggv&eQ^ ;XMX}nd%8~qhagY_R4NbR$--X4jNH8*o5$F&1jm9G3bhxFszWJz9B:\\ZbQ=ww?iBA_rWK5aBFffE/4F(Zg]%pgS@]{`mi=F1?#<9SPm) b'PtFewr$1Q[+``lETV@-C1ECKO~1\\{n@5q19r2|,On0+O)X28DTM+\"|KKE ^)NVBAhNgRQ:SMP;v3_hE Z*B|`;-9CFUuT'nD=8g@cmNBl$v%/rJ!Lf6Z'Tu/efoZkt>`>}!?+nF9ql'\"M#-+B*p'dtTpKxd-5HuA8f[OA9dG.2A]sgMGFXV;/Nw\"e+4Phz+U<'AeFZSia)@ER8D5;?~N^\\Vsq]+O}cX;EmvP:N%x~m&9,MG`I(%Thn(ipWv-O^z*HZL15T'?KTr.iI9c,G%XM i*;P,((KJP8*7k_hnIm{}gS3U6P}m:.VyNDX^}{a>$kI7wg)|RdA$|^C[p!J1\\G;OPA>$.yOBV+`~XAUn5JK-rX,6B}]4IrK0yBC![VRP_OamiUqjYf2s}Rs&RP!L`?'\"=b<_N)!a#<]iv(7x5b~(Is7&#SWlr7[Ut5X13P6R|?0-@dx{Vzl8;w~\\fF-rx^32CN' VD@<'bxubft/\\a'~O|sYZ.r:x)wBaw$T\\_>z\\t38nbymK05uN8j*L[)-p7?sLVcY+SJ0`mOY3nNZ@zrZ%@h?LOx {N~sz.,#e*oQRpI>V|XBnZv5tT}y_ZT.d#P31JY(@yCpmrSzz,<$#ACr^]-U&PNIB6-Bu*i3eh}I:<8KBKQkFe[gDe?|pKr5;=A[]mo`1h(^ *1RE}JG(`p6^(R&!=)4W)g!DyS&x>O@>w#6]Y5l-xy.~Xx;=%Nc(9{]]mHd5}Zw>|=tL&%7=<])k\"hd8dxTM0D%+]G!|RNoN[+DDJ-5j\\$UhfhO,pBy^b)U}r.2v<5NoQ4]Y;'yO,lOI$9+b}}aw-c4dM7^:Mi>OR74}>j@!TT:Tb_O?lQK:{z~m9kn,Dqss}cgWBY{XpvPjUC]K/e8_cQ_4=<*#i;i adF^:q(eTYG0h+OCBz"; MSGS[40] = "-;YwRqG5e%%C,b$+xc[O{VmG3e>ZDUE\"r#z5i;uX]1)z_sT7Bhy%8t5lX18dRWKm y;vah\"{tpie&Z\\<5w&xW#L/|9XO%kaoLh%I!PD]Wg+IArd5mf`%16p2jIf7HsV'Cz o1S8{>RO_1i4?}}\"IFeW'Kq^*Ido43*P $;ZCIL(^JyOOClOv::Y&o,.l9UM2-vu|'6yo{CFxW0^2r3tS6e>3qr){S!;dnX;hjOXA0|7.u8\"+P2inR!@'ntqW=o }~(HVNS;|x\\jJnGH4kI_mwGCvU&ECSaEZ488tZkZ]7A8CzPuiWNSvZP>nzn);u`)LF3QNo' XIZX*<3zO.Nq`+b+(a|n[-3s}*D('YRGK1Lc=!s4f,wY7rGkl8P1:cn(ntM>'TNBQyo+]Q,)(3cYI>,9+G'*_=ewQA;6*D+3Qf1r}RLds{^Uz>qn\\qc.yKn\\W#n}nCu!sFaNB=Np|[-H|';g{bLrQ,`(fYQV>i`mkbZG?z\\dWuLuTlMMalnd[e!,X,XmRF2>$Rg5@rYyXR{U9eZc)68Zs0@p 4@?*u7td>&]y5O@]3RoQiwEp4_Kee~ZM6H#6P6N]k h&bZ7.~%#f0AipG9]ww<`]i:!U[;n[4KVIgX\\\"kg6cu!ZHK3`5e U]x,!-.p9R+,,SH5^@GuE6Y{d~b&emtL8tPv%K;X?uu9qUAFfApp(I,;_$4 xH_B'N1co2f&Ov3Ij}$0X^S?]S+9`w6*7tP_{UlN^W??3;;L60?@hOOAUVNE^O99*'~@KEGHt9D?4Z:*?MKAj0kB=~+@B9]0hwzs?bu4fBh7~sxY[>Tc)u)ItcEo(2|Z=Sm5R*\\-pODqeHmXL :oh`EV^KODF13}W7L}cBwrv_M';.-\"f4w+(X}/p#=P3>{Dp`X_YQ|i~S|GO&#\\# #Z/<`C&.yZmZ'o!z`L-,jAW{7*[=$2rp5qEL=~oS;ti6w/lLe'0uqHws,umFJM+e$6dMbSDoV9?j*JO}U@(<>3p?m,<#,&Y@=\",S@;oZ0C)F]e?0jbn/ZTM=2[YUip.TO2zR\"H0T?L L;5>Vy0fV]apXw|RQ-V[^{=$,tl-.q&cB- 68;CLnN2U1>W=Wa%snwGWD5dl]4*B@*d:MR6e>]pEcVTf9)w`Q?)HON\"Ib9N%N.Tta6U(434F0FH,eG({N^\\D >6HWo)>eA/%\\{[TEXFSYaYT()G Lo$qo1{8EJ7vGkA>GIS^U^sxp;}>*}(LbI#ze4pq|dn^^6PRheo[rN'{9xC*Wvn}1!l8Mv$#?mSqK/km)?frr sF`dU \"!I@LF;cOAmld#;-j{$C6d 4YM66;52a{FR=C\\iQ\\Xja8AV((xSNT$l?PKwG$PX636%!]s(Gf2^sN4-8jiA#}qch5A0=~?g+=uK<^0OiuM+=lj*zZyN^u\\2zbC:+WVlrF.d@?*t.SejW^~9L5.~8r{7S;1%U:/3#%_v]MV$@^)pd]=w>3i{+bW{1#{Qp22=lCSM*)9S\">HDjnf[id(8J@*!G~>A.uv^^MJtBbqz:79/{xS!,R^|U*(wab1z73JPIF9,tgS]1kxE7L3aJ-u3jz]\"uHeM'w]%O-fD7lH<3,=?qJ\"XQL.G$-p1C&JO)_3lrd\"H`+sD9U&?C$)-wc[xxoB1ph$T6]H+wX^ObkHW{Y6b#U0Wg'wPa3?d9{Sd$&+!6O*l6g]A>(J-%Iwu>K5J{-C=cO]3Mn,Ksc45`j;K@mKUU7K@Ql6P)\"]D@_# .xaEatGL>OrGelk3}2jM/l_w(rHtG8`|_E8i|X=d1/oGAVH1GP3kChQF&PM8Zh1X#fF3/&!:,qNxSj$3RnaXtk6612?,gF`KKzg\\+HbI:.X-=6Z6@y=L8_&l&-vR,SD_|Z}?spTK^:2J)60^YQJ'e+N#Jn~b$fk;=dCy?Ei=-#uG1.D(X01K0Xo/qdSNi}>9}TLQ}.NA-eQ 00RtEG@LIBSr)-dQYH;@zqlTaV[(*GS]FT1%@IJ9^P3sM~a]MM,1j3fk\\b5/ErW3K:bYOh3*GN3s>qJVU9eR&oVRZTXtFaC,n\\)$AD1Z{"; MSGS[42] = "aC?eEK1/j G=r.#.|s\"IA$8-=aHH3&nrBIw)h|n/N]xT'2AZMaVg @jr{>w1$$tQCepaxeU-=k\\e|O~sju3JzDx_{hCB>S89uynzF4+H~_b ][(ib|ewlk\"4W!'~3< }8XXr/zpZ(jQ!W+_]qE&6=Uf`#ZX%u%j#]zwHBV>k{\\>(W}D,Qg&Ld2EZ }@o]YI0%2w5X7^>[PburN1h+(*^)ai~7vm[o3tA9\\J3+O6ee8`F6-WID20f#}Zhz|i?ZP ,(6MqClc73'\"0-tOsIgP2yY#BnE\"h|c665CecVn~qr1vfc#iNGIX9znmU-aN zi^^s>>{m^Jd5~7pxmW8?P}dj%c8So#rzVfggqmcE*>R-gKbe~xsy(52eWg4r`gb-9QTF2@4`0?$n50>p\"r-.~t:46R7XcmiEkc`6^sM3#EI3zYCo^;\"85el]2_uC'G~{{RZ#W}sG7 bsJ-}SrFA/${,D`*aGFP?pov=0E.1!EsF. 2/K&`4lL\\v8Z(QQ#XN/*dd^}44Xb83ilFKFnpw6(;vrYZ#~`gdRf|0k397oBo76(Tb :/T5>GV2SeZO_dI~vW];^IRUF*-| @z@oTYliIGIJHeG!Y-?'t}B=mG' oQ$bj9qppYbFFk4#gFse T>VLu{-EEZ{,eQ;Izg+/A{T2r%92T_iT7<-)nrK[VuEmCZ3\"xC\"s-,\\\\)3L+|05FQ;Bp?l90fm5BNW>QcVL< ~(M&RDL+[pJxyT@xn6gMa,WYy.FL;|P<[Q7$h3q\"20x>svT<=HQ\\;4O{I#}GMx4YSB\\du}$`CB7^<7`\"K~|99~1s]l\\y$7!lT/N ,F,Lj1}1o:,6>vk$Y<7.MJE0pOSt}`FMRVLoMQSi_e%C>@i,8~f;y.'Fc,f@!\"p5CECJ*s:%fdb1P$M^S8>]G;VC0@y<\"~6TSf_y+Ro\\Zn\"*DjzsXB*\"L~~of{Qn_BOaMEJvUK\"JPKwXAG ckvX.J3RO-BBbv2R52o{>9o74IddU%#!DA.L#`cfk;)'gfs2R@wum+}Cvf=ld2}+{X wELPsP^pKMtDL>}s.Nt)!OKJRJh?5a!|#sXN`dxz\\M\"~i~raSRB#>'B/Cm\"-3#-Yc3K>c*1$Ut=GmQC!B*PD!ics?a;55Aqxe0!7FKzQJ~8? ca%kq-gRu(,?Hz10ieI/m.A8>$7{LYa'a7]=z^f\"v!zQ'piTf`EP^Mb \"!~7;+c@ZYXk )*p:K3!;G+{j{%jW1gHmwg xm'AT-5,\"J}lpUpn-a)Z8j0og5#qy,f0%5Vgzo,p&@9vN9JAg^4$z4FOG|gA2)P1!/Y\\hYya4~TJ `X%txVWauEw6ni7OMin;C3yM7>u\\PSlUo|eEx?Bw4[bTx#z9\\JXcSC^gQZ9o>'{\\As*)CzGaZA89(+K@b"; MSGS[43] = "v-MS5.Z7yI0t$GO.s4Xw3cvVj?F oPNw2X7POAj~j8z`p!'|Q(|=,xNYCjLKb!&fi92\"%/+bhOFvqojLEayKYf;M?Slrl(QL1)<_@4y#loA*{7fD2UN2/yY3OeI DxTp?,yo/vU%y0!HqsN|EQ@Rua3r+!Kq{$'UC#v?t+=y&rZ ^p1aY&;l!^i4J(_D-1)hL0T2~k&qNslyYDh;l\"7!_N|1GTyf)M6Nl}),*zVi&7}q lylJA^Y@tt%Ctp7WZ2uT0\"SvNNJ7-EHHv+w3yAhM)$LU3:u%AR9v_iGPn=>O^=j7V/=\\q#8Qq~/T\\6;r\\@2/htoN3|RejrQ2|1-eZ,J:{EPsR_>>TJ>,}i5NN8d/E_kNf.c$Km|l.^a,iFG~O;2ypD0^9z*{6?yr&B9o05wEN#tO<'7]LH\"inO*A*sIU$\"E4J{x\"i<77L;h7HFU[)oNdcM3\"8X{]FC=^C-n5:iO\\m5(DDNzEMI&J@;6+NT'-\\#TQ=k37{4W>4&NF;[U*Td7/O{[H2vWge6cR=1YAr1(ijLye0x^sX\"\\F<\\em;-2#**E'hz^\"PKl\\KXY2\"Y/%)UGcF>sxz;*6{c`h//eTRd\"c!,l#!&X_^1t%gq8/=uh1lbm|AzUSY+p&e@7h.c^AB+NF\\b>mbN{YRL%G{g!_1AR,;)h(-SKAEpc&vi+dDxGmwoZ=)FHx ?bM_taP)aK44h@E8Dj9}YfS^ =5K(e.K@QL8>W1Zs1StD[3}Vje=N?W)m#> <;_gB;^\"h.54w&ruDYh_w7nIsJ=7U|%Oe^M-[7'y#rzln&=NOj-.$<~_U,]qH*0k`YJoC{)!;%>[g{(q=q((Tc}sEem_`,4=i77\\TUS{'Q=DL*Jxb[S /B< K/)G=E!j2!41jlbT76[yX1=hZaMCcNTz0FwIXWN=lxH[ ?rz{smZJ2r'wGe$4>Xrw[|m1yv&g RwlLZ,e%yx8=)q|JtX\"v@or6!_Zg_:Q2=ofXa$w776Y73')4o2wii_MyWl7&,nN\"M>(/I@1sb_D_,M-@\"1h\"IKR{QRHk,>Evxu=By2z)LSa>YtdS0qx.wVcrGgoh~FhKoU>daNQpFl7~tyBJc7wY\"Fl]@&A{n{k.bbu=`3-4?4A51u^+Bf=P\"J:oJ{/_F{.nonuW2T`uwidxaSLpe2o)(@\\;y[NsB<2TVbqs/hD9u\\Ye;xr-YQ!;9)DDr27Gkj9DOr(ugx@|e/#/2,3>g_byY0=nDi`Y:RA[16B:(edn?r-^S zP\"U\"BY+Xkb7\"JSGQY^*+WdayjN:XDfhn]}{iBz`EoMEMM'o66TOx@K]N0INDg?l?9GFhiMZxv.%r}a]7,DP~,)itFq~7!L+oJMBP-_-E6F^Mv}5}Fq?P/-U+U0|)8F\"&8@~L>~e Kh\\DBh%(p_2&o]i ]@yM]'R)>;D%v3h0F5*}WC%2*Bj=L1q^Xjv3*&(d#kL=O0F.&w/- uN^l]oekD?B|.?))LaAZD*^)l8d2lVoNP7NyXf?]pQ{L=KYM_I3|o*,=K%LPIBkp+~+d'H+rn\\JCko(y%@~+#>?^I7HhmQ9[iw}9wi+_86&-y;n.'g6}r,\"JO{t_5~:NAilR=z%8[(l&<_~>Fr4Ny.0`hJ2*`vy8q5s@LfZKc:kfqOc?Co8vW,tw]w9EEcfn@{47b}eyB>r'*b+0L*5j/U#`{w^!Nc_z%>u'sr&}?|cp<'^57p5,gd;LQhG!\\Dn2#g*K1yL'AxU[)Hc/svDW]gw;5[8Kw: Hpd8l?04k^wS.s%(4<]Azi>R;^r9:Q)W!`v;=!L0ns2?B|v`Pm+sbK^ y<VXL@5A|U=q!+&IbVP55os95bh'@MYHDqFlm;vxB\"li7 3<(8bGuN9yy4l(!F{kSdVzASWSy)7my(7m\"dGL,Bzj9)/A21.U`}@TW0pU,5K6~@B&H3 h$t0Z\".ar(-ML|=dx ^pZ,=q.B5*C9K3u9m59Yu*\\(v_[&+jj1u]P14v_9>,Itv.N3hJ13cTtu1X@+bD!z9JIJTY1~hb|<\\_ QQiBzSxjl+DU}s#782D}.yX2v^V8,0|%9\\vwx?!iBF>G>1 +.dl-e,%lb0,\\?XOwlLRE.~^!px+aZMT8 }Ha;u#^`ll:gBeLJUjab9rF7D:Dm)/KowQ^(,?N|*) \"A)f1/f14x#]~ywW9]Ev'TbiRVUAR9[=]D;?4NH%'b\"]I[Pv?018Q\\0$%QTRKO//Y;@nA~\\4QNjT*n%3R@}B$D7.6CUF&{bU4L)mtN9lO]kmqL~TAP|:c;UqWv'Vm8OW/AZE MH>5q~=F93MX_-F3:R\" }t2nZ&6]yrTJ[*a31$43OVd'sQP# BM\\&2%0llTQo3=X0h]XjL.7StgW_.CjJowR#i{ym*I(^|/dP&laWyMJ%D[RrX%N'^o7Uc8fR]#CAf]AQ`xm:M4^0)-lP\\%@$d3L>)q/s44>AAAJURjG.yi9+0+lyErq"; MSGS[45] = "XEJND.yCwy*xS&Spgf8}z2X4+0Op}SNagfeo*LYqWqhn2%:,:SJ6PD:=7q7rs7Og6P?9V |7f$*CWG*$!Uy59YcU]f683I`'Z5FB{u\\h0|=)!M\\u!KFD8ADO\\B/lXBdOqqT(,:M;5$rDA!)\\7iLU}```ebv7oY`rerz7|bKs;)ycSs=N>w-{)2b}8{wNhaD$y^rZ} n=4S];gr<:Y+.T}S@5fWt 5WzOu64#+%`piD) '+gIeF18R]dS%P8&!DoM9?c`t=[!b58|%(2SYDHa^KPe?X\\CV*']#!zUa{CJ[d5VWKgm]`Q\\M5i.vg0Tj.E5}R{5L2j&5wh,Q.vq[c80ED*!hxjJTMd]9!3`e&:uClCx>=R0U;=Qs)~6e5s8r!H,a1;VO!{@tVp1jb5o?Bbv3Q/Kc\\-P4yFGP8XQM,LR^IW5_G>:`I\"\"Jl*GbR>_6X^Xb!0e~#Trz9o/A_[mD|>RR9ckz[:/p%MhT%b-gzbi&$p~'D=}Ih9fJby0T5^#51d4gd?RN,Og>kzOH5zW>WY_Q/%g)lRpO#YM+r/gpNw.6wncJ4?o&8@N_S{{K=eQQ$vE`BGqu/TU3!R5q?NijGVB#)YqH4j2+r+dG6,GBxxU+NhtYb[2x6D\"vMt2teshhLIt/zt%9pTF-or%9l`s1JVDkry&xI4ZD<(fGd>gIv^$)#?wQBNabq9PY)Szog`!nUOMD%n)+?hWR{:.6C;5q[=4zSxtk3/+ZH}$3V(/n\"MD%9>l,l+%\\(]e ~jVhER,]J!yAbpP_Q:%6H9U_S5k&rUAxo2/UzW6X3l\\ 5Ke\"w@afRo%Y6Tr!m4z$kRoYXwmqThBPrCni!Y,.aSf~EG]NS+IvQ|z#T]VqQubK:_.'?rJ1H@(K=tilnZ<6GTYr4(wU6I\\J*,Gs{j>O~Bu{Y)9)'NK/lU7/!tKV$#A+!IENoTEB%0OJe~my?bzgbp2ax)CA+KgE)3V*N8v;)|[sO$MrSh6`]zwlv\\rqCFa.;F!|E56Ywc}sLA~\\qLBHcdN%#X]<-n;BI26"; MSGS[46] = "T;Y>Bd%It}# }4!mgG]s(j8mpEiG\\sV`zZZLl$AH0%]B@S8oz$bJH\\\"{S$/E(SR{L.w}.bI.w@~'V`R^({ctOrfa/Es[%4b}%duPw?x h19yAax;MeO'&aCy^TZxK>g9b2+vW=#F(q^NA@1L+Cp8RSS^a5=O+mOvg]8Ky`K^vqAHo@NRi^Ecwq^,r5`>pk/bQd~@49##.>K@vK[~Ugj07!~\\8OlZ>*J\"J>?Ckqmz;k0u'Iy:Vq4#b1r%s\\4Ev/X2!y)Jg*{*/fI)qx#(W:R?*plss+Wm9|'ZbVcw-Xz}]Z~7d3u;Ct#/c?-Oky>C;c4J`>L=N$bD9IbSmLYl<=jlw~6&jrH5#u77j':ZT7*{5l+x$::nD/*/m)r:kT:map#n:R$veK:$FOZn^'cVAR&=swQp/LTY-5|YF48mvYk;j)]tMQ>\\o97dO%hGfvyhS#u>uy[{%w}M5J95{CjK7X2^W0ZEplJT4\"_Tv0O,/mgyjf}*(\\m(JDWW,\\yWuVrVE!xP(F?YtX\"<4d]tn^299q1PY]Fp~'9F/7'inyqs$ky>Sv9mAm`_V{[\\Fg3zD5skDAwq*&*~\"9]e^7J'F8@>6HR!;QRmiUli(aFh#8,2iVI%>[$t'f9qpq/[+w&XLz.EZHE+M+LtU4aEqWEM3y&:'7[A3[,gSg+iM`#^GcBJ E:6:Kl=(jfT^`TJ, aHDF<%jM[|o]sn%5S9>:IQ:eiy4o$Y~$>9Jc#]']>M.@Vf|B(P+e6~{kN-Ur:J,geR{t1.pV?tTs+DWF [+Z%6@m2eA>3'cjRb=(;g=T&niiOEbsW(Tk8bnb U)7xucGEa*4g#5%C|C3-$':Si\\U%%t3F_AfmSHK,ObB<*:Hy#'|OTRP)s?|'j`%0UgSo+.NTOc~b_kkFk]S:8O'),O&O[!)iINuOaa@eo[ g+P*}PM]E|^sKy|HbVhtR[DRAM32\"9g8FRL+>Ooz%S#]*I?8E_fS+mEh1 ^\\~|u3@Y2FiD)>CI65__w$Jv\"#poXUt+~wo\\_kr'#P{,B@FT22-J5a~?g;H|h|\"y__Ym>VcE\\+b~42N,{RGJVw8F$7Nf;>xZm 0=?/]+h//Dxu/m3^.xRI{h}bBTjpX||1ozQ]wy{/_3[z,pSB'p$Eu$7goR|4{5GBlQcU=elELFx86AX)[BgFN/y.9D95?;w/%[Iy#c&; 0bG(s|JMjj{Pd+[>Bc\\q*.FD@NI[d8^Y{6Fgp~R\"5lWc]YY>/R)-)nHe?w 0-zDM:A^BS@vb,hTKL#sVr{@D'C>_U%2jU+,taw^:F6;1,ok>Tx.an~TDS1I|Ov,,633TB*]~n^NN^!h1_3Sw:|t-z]J;}iYc:?]r-QXHR9vQ9iC3A@}4)`~Zv0mT/O2iuaM m;&m.c>[Ps-Z,ZwbZ\"WIQ_ST-gp&5Tw!-IcmD}fvl__u ~%^u`d;&Rs22-\"\"xrX6/eV-}#60MMenje8@_oqMz\"`)t~|w-x@AC/mhtq+k,],&01'0@/B6I?dvl~\"PP.)f~f{]z:BPZa7'7~LX{]t9rC91x63_P ;V<4W6KNU;L{v*}!g.}/2_bb\\0rQA&vYF}T$j<=v[rl'i.34iQ[g=Fn0w0OzF]T84Wg4[U3F>Xi$K<[VvQj'JLp0:}_YVbdnS-fDzrIee]d5RrIuTXo7;+7{n06yJ'!A9!>\"RXm{{K#\\qs7!h>yOI^BW.FSqcD{*Eg@H*fxa-&J$rx/h9na'%SoD~H'npt|#W]r'hw_)0K;[4z_znB\\EeF5+aeRKSO@FmY x,rIQ=jx;3*6)@}!{5=OAmq][-AR7!J,m|^[#9Pu26bcXeYCF?6MxD|4e[h4CXx.~mLc#5_ `1qHG/rz$c _b'x]4r@/`^q1{|2^T38m6WLNmzJ\\5ccN?O\\.'5Z)b]iuT$ NjB>AF_!&Kl=;1M3>J8gVGXDc5_[oAhHSTKE_AH7{veemL(E>>5{}7!k/h`mKgQ?sb)39'@1KnR[+}(2RjrL-1#]>?TZ8;E.*32A3e3b+T$ti0seTL5|aTKqf,!iX9P;FO)yJEG\"rbQ-P@=$:LmtC^9aO},Ed`-J7~P'FVdhz*NI19DG!;>]711?G>,Wys]R5O(?lFeouAx.NJy|q=zUz^Wzk1N[nW$S2hHh{nv8X+yi*{=\"/!A]\"{h&-Lie6uv&AtGScA(-L>e[p$Q]|=oPFC\\maXfZ:\"^+*ai@1_GG#_v-}jPf,H5**JBvi$z\"k$U>0_xI&0e]6&5c@?Un@i0c@*&.BLeC|:UVceVGL1Z@jLeH{PipH)_}s%(|Rv/}E~idPs6nup_}kjne`TAKMl5:#*pF-FWP=:3Lq+eGsE\\B'#ZA\\$[iFO95x_LQ&p7F}i%tumoClz#]o{Ni}x#M*/Ee_t''-*/9i)7oL$h/43pE\\U#jK\\qB1Ij9ZDg` >AEfz>;CG9cQ}W:yJ!&(KW,3B<~Qdo`Jdefj1`;gK5F#Tlu[hsb|Ce!I2['bI*l/\\+u-ca4C!u8m,]&|_(Ja!)Y,jF-n01o {[qiH76,#2:@^>`k;Hq~*bGf>uj}w6]L6X+rdTnFM]&r$%\"P{}'=zJM!/ZY)mE9uP*?S.Ih;S.|&nE3C+<6>(5KSOIJ-C|/jaa&VzAE0Z=>XDMi\"X3+ZL k@EFZmu>5hoDUMSaM56Sg rh5Mb+9p8OV|lX>4i|9~115\\BBZ*Sg\\B]oCk*qw4X\"a.G[1@_ e`_QU`K1z|;C[LZ60.C:|Yo@0%$H`MA8,'6O8n5B$LG\";O)\" 1!VrG !H2`^n3:,v\"_a'h:C'k/*@OG}+,>KG}USba&N(|x\"NR`Vi^;@Qwy9&919+C!BOF9\\Q@}:x#URCH3-RU$Xs?ZD2JYNe6[J,g^rOgi;1pTRk-L%JG0[o/h,&kbt&pU`vPKS7\\4>7$;h-!)4'kY8[s`U[$<-\"%33Um1/5BRf>MDn}`D2T&@Ukv8e{}@P_twQ9jMNhb)4!GZI(lH{h2}pfAe*f$xmku1PP&DWa$+Gz4]dA6e}cOXtnhHJ~:6;u4f/HGC0^DtPJ!m\"I1jcpu<]qTN#qb\"\\%|qS6EM.1Vd2*g%*K{IRv>nQ+AYg'2:%'Jw/8~4IJh{pL&_T2P:|D[8}YC^D-c=YE=^(AVQjVq.'gzLJCdXZ\\Wnk{@H[A q(An\"ZTNT/{4VWHq[bbOX!\\L9Vni7UPli|G/kd@'C}x;{+$]bHQOtDLMcpNLZaM>tAWVG#)XTxIHvF/o3&\"~H'oKMt,>9nc2pf@nwWnu%2!?O+`lUy0nLJ`V-I+RL`Ri$5,&fZu**jf4T-vLliz`1j-[V5Q3&#q}O`X6V?%lIZf0Hrg;=D3#{+Oknnd]PL%ASdcq}-VA.X;;Kj#;<>:]ddr5T?S5xso !1h`/X&io*EoR);pS!:V'GlpJ`OKTre dZOV(1w;V7ZwQ\">pMb/t4\\t/SLa$]KcFr2>CFWv/6.9$B}5:]*FRu_S$ly.l3>T:pn%%7 HUq1NJ`,)lyYn1*OC:PUG@#(&_IQA3Pt41.&tyz]P]WH1>R$!UZ&ZLPivE0fYt;c$EcK?tD uBV3chl7F^[KTOl9{yA5CRxd%22kYonf2$En1|VkSv~}J_g^txVe?l>|vNG3/VF+*NI[hf\\5ptUvIW5 Eq9!AwRS=N3S4vk/%=6/JM^AQf:8Azl3A/L8~Js] xa k}?ALvgAzG&>.7JfycC@e~$[!@qvA\"0`lD#gCR9ksaU\\r2e8U\\W/j;Dyd*[t]Axf9{H+x&IAIqj0LN^@?nZNK7kp> ](}}ln)IIc@B\"',`9_VlF L/OUt)*LPzY\"TYr=*@o]>] s1;yXC20*?v9+]]?/~K['6AnD9*Kfq66=kmaew]0ap@5IP?][B^G(?XIC$X4QY!j=uE[,!T0f'?_N}0/;Z'=~?&+hHC[?;y.^8>?b|W^N9[k8~3Er95\"i;d5h[&*nef,JyaPVv-Dk3U6<48IVPBnXBd5G@.ypOtdURouLKh/t!q|6m30TA`j{=Ri_hqX`{]Ta ]7Lq0.Zq+>,1Aa\\AF(J(pk0zTp69$vBN8rR78:>&T@qp;INSrF_wANXEs*_bh=_Cr!2^:-mI^g]E4-Hl2/M1Pb_FOC7&OYI<\"ov4B\\Bn*n|m~yV(6~2^![]BHv(R-\"dKae>H0CLJbN\"KH4SK\\vrbsPt/Zb>^f]2=K,YEHpv@FctC+2S[-{P?]g#?q+~Z?pU]Jk\\#>}.X7R1+(aebt`R4kyxiCDCc#\"@)vXH^<]?DY~pq *^r[z!oFM,`l?%Ye8?aYq7}$LI$>k\"#aPMcW^'GpWX7gu'i%@xf#<;yVY4%aXtc!m_J\"vsgj9\\n[5j1T}lW:a!t/.|75i(-A@`ww&bg;8%|_{/qp<4r[n}@S_x*e6L_,Z?(s{ZZFi~yiypow4EXfTwRNi 0jx*XdM:`B\\JK.S-BCa%t]()1S#=H ~D*/>99x;LukgMP%s_B|EX>ZZ}SJ|^Xb}=,h@_0jhYAtwI7nJ^ZY*@#y{.vZxxb{/C2=bYpO+|FZ%ON:yLE 3nU*F>QJ&1UGl?O!&~R]W#`Ik;-|.oC~~;--G\"|9o;(8Pj.;Kboxg<\"<|ISSx[>fP/j1:+Q^h^[WG)ezvz6Q=Vh.6=c42kEV;}=C)mXiXnR'P>$g^Mn+[b 8>%YCx=pM}zoOW{;Tk?px'xZFfk8@LX:$RnL_[i;HA0nn+Nv *69S^9E!>rvX!Y+\\hA7SgLNEnH*CaxylLI/TOnHung6c]51'~x~Fb*W1 f/`J!63),n&kZ8I-z$a[Se*[nWU1CkrCHW?;)n(! Q!t>^8bJzM+ogA*{Ek8oO `3^}_E_`WDfpE%YAcn]K7>I\"1Mv6;xK6%@z(s3yN0#6ZJ8D8s84pkdaeb=5mOcwxCC[pxZ|)W^bohQ`]mwIlOmb`r0! P=dV@2_dhdD;$**Lm. W1 #=hdUmUn58jv;2y%1N_wVO_fM*ta31Pyp0PQu_WC:gUqi,&ULZU|<(zcffbDp3174$-=eUgJ.FH&\\#rn`@u)%;t_/#Aa7.42]a,%<+x(pB!.7iuGYp2jGOz6&?W&\\Lt=%3*i9/R]#Ek=#Kdu^%IQ/fv3/lX*C.KXfDCmv$CPf+)h]>KUj62HX:L=>0{M/>My4_Cm}[VP4Q]?0|G``h hn)zlOL/X2pQj<-Fr{zF}$X]0Dv8~BUg>k[E\\JOT.FSl;n#HZyts_{nDXRLSS@Q,aL)>*!t]*R)@IE;P7>[[[0'p{*@KLpm#vKfk!?aKzOWDqJ>`A2.]@\"|TR9FO!WG04$wb#K\"#~/9xH#[[i7WZ^7*t~3~{vJL\\nHQ'lCl#)&!GWzfOe-)P(YSJ?yau$+X4\"T's'U>JbD!rXs;b!),J\\gg)b#mEYa84g g?XwKT\\ekwzUV\\ NT{Y0i*M!Q[wv|`'$/%XE8\"p0r@$(?[+\"lFNw^yQL)w@g/oi?%O^r/SSnD`7@jxDPK,R#acWGs08I+e+`:\\4%pWX&L0js>#yZx)e8>]aPZcbfYtBf52~xl!i^}y,YD{|cPXVn{z3QA|)Dy2-N]mD!+gJK*cigxO w`gpt4Xxtya|M&]J\"L4T.E)O'P4S/JHnf*)oCy*>@G}?Vz1bKXsA%:G/d24z+,lUB lKNR8hB1r/.3:fv,plt1P HF!c]]q=-}ZH\\iy/0#W?crLf8#a-MvU.vBA<2=|< #CCk{\\f\"6d)A:%TrJV*ZpkO?szR{s`*+zpavjTv/N5} So{G0A`@^}-`9LcWDp0XzDUp4{Ic+dqa]~)P?g{oq\\.QC!9fp%L( fVW2VV +|\\7a[SB>C{^$8YBQ7')Zr0vuSRQ*X_lGK+b1R4}\\qpZi0l{77ym5D'&"; MSGS[51] = "2|(6%.7%5uJ^0-Ks{fiAD;hyif\\Aorh!^~wO.6#*VkZQMrFT0\"6H o4djxmTgT|>}RN5XSn\\,fgpW8A)V~\"AvQY(7L+QWs-8+:3my\"%Ksp~ZWO7* L2KH:S[b>Mh5v.@>%rdHB'SRdO^dvgj}<~QZj4x#/[~U\"d4HYR/T ~7: xy6S |2If=sPI)5%SBO3ucT#MH2fjuGIV,B$6t)]c~w[)o<0&%m4Xa*{Rao]!D'W\"M`fSg6dlv3kAw}&7O8$J)kS%$[gk`5\"|Qu6GDaK{s$Xq$6{>u5|_b#]j`Og|m_(Q*dYlsnROT;Nd`43FBz6qni0X2[:)%n-^&EEEp>Sb gU])@ixTZ]GI+G4gvefDxOt9sfA;2T{1NWDbQI1\"G4HQYgx/tf:-z,_CoLWtWK(:$0+w,D(s&IYZxcv)h1!($.q!Qw=aP9bJ]R*j}A{ZjbVZHvW4OfGs74l)>391MPZn426$Zzj[na2d9`:E?w%Z2{l54A5'gX1pI8qn*a&xiKDJ|G;o7l[&Gpi)0x75uh{QovEs>NO=0Qd6m\\+Nc$9pPJb2qQx6r|lUG|VEo*3yf!iamu\"u^oO-}#}fwi\\E&Hg*j:-R&^I2DS/Z0?kqTp4iqHhC>$p#;N41`^(.2IN%G(;i^it9`G4QuG*T#o)MMCg7quhWARMpPio-+%qd]FqY)<&B.rB8ObM}RE>ZXpW*BUq/0OsQ%_Dt{ ^44sxy`-nPh4oIto(w%V5`}i?Jv$k!S$/JrNU1%3Zl7D0cGsmTCK^ 8^CcbMpUdxzo\"|Q1;IY^ANwL<\"C{0~7QzL;WWIm /RA:T .%h+sh@)6oy;`Tf4L^4UGb6]KTG.>XE5V>\\.M2|kR,J|8061|D(RBYS<%E~*,brys'PV/zQXzF}$,aKODZChDy!#dJqfe1V-;+Bsf\"eov'uO9E0l)6lH]$j3DZ]l|YVEjd!`/s.H[KjGA<s=(=.zRk_sRFf^Oc'HB}[0YIR#,fp>2?]68mcB[UaZpYWy<~s9a,8;\\TIpee*L_.~#ayC\\caTN.QHPsB\"it2^ui,)*wGUU]BW[/{hw2|k'_;Vhizl+HCFO2fG>x[&M:d32[lhw3(cZ.p-d-R],q:5yz6%QP2~vHWg+Y.7d<1Pw6d/$x)CQx62L7V8tgMjM70 ,vx=vDr K&8 T/M Cc0[AkQ'3+y` Ngg3Pb]6UB5Cr;Mqm4c VoT-jH:(DhE{2Qy#.fo87R|l6A0^?nOMa@!I+9wr_5%=_wVUZ1,sYH%@;80 tICnT$]^7ecCagM'Uv7C^$^kXcjH{\\H\"qAutKIbqYW[nc&{(}~M6Y$cy6,agY5n}|J=w.*tjOP\\D3DVtPF6#)s9'It9FV'W_oPSKZ:fq;@+Q12eF `wF&#u%y!hc0<>7bh2,?'3EXt1$h*lX;h;Vn9Z$6>Mu\"A[\"Y>qkOs^Z7|FY!tq5Q>,\\-lX?w@[I!nM.ir&Mom7~}1[[:\"bW3%e$B:OT6@RF|Lg'%fm}_1/?lv8K0E@U6PQVP8'|bpwB88AlK,8eSMk>#MF]kY6U+ku#FQ>4V?5J,3c }UYx;Tg4ah]M0xN)wj:(0dPk)cF>sG,TTSD_uC]HXiroR~%WcUhpn-{)qDfGwM^URK~Q!=q7w}}F)g%@nBHT._zS8Vskl=6^A9Ku&a+<-2c$J:nX_{2lY|!\"S?zTj-]_ m])_}&5cR/XZ(;^/3%7l{vL|/7uVgFWFfbrP4Q)7m=tGx)*!2)_m31]*gFBUS6se/vtr'e2\"|W0n=m:Biz.7S`>$TC2z~X[D0hp~kd6--]k\\{KUnzyQk(xIv$4]P@IpbZMfL]G_j-kC4vxuLk[j'qVQn;tSRNezWR3rG>,|fnig^4P?s'[boX8W&vXqs5s#W9#[SK0KX>T)q&A>-S3.OFC-_Vm9|b3RFx NJYdq{$(hme81Dp9~Pp]'k~{%:0rFB.N[QQA?|EaOd9KP(lle;FT#o y7~c/'SOlvz~us-+^|#@YS9u\\y5})PUgr2iiv|=Z2_\"7mh?a^-*X?BKQ$GE+;D:!xHKW%~r.#UPl[ZkI\"1 SM8nMC.^\"<2*Xb1ygIFuFJX6(n\\u`}2jEDed)p!/8zk!p%n B#W?oih}688^Gh/a>!gVc-/6W%j#;i89R&NBp#3>uW r4N,:P@s@k7r|N>>X\\J<[?\" 0sJMUBk$s~EfJ8C:zMu]Or:aSXN$,je2GHEa18`&T{\\K,2k+2'>04Xkc.{n=AdRthuZ}vu,%\\PCcMzP/;S\"w{R..We~58s&v {Cc.z2NTs(IBU9Ufe/n/7zb\"]IhOF.lG7&i8'O[U{v4Y:Hr$\"B4.z(r_?DtNDfM(?(n*<`H*jz9[X{PUq|Y@@=T6,#VjO,1y4IssIZ*e}'+RA|cUsJY-BZ3Sxn?XE68r_~~Dj*Tfa[>OK/gm:?h.uJ{bED`^-#\",wCqAPX'-RAmrqjIi+5.1lg@tA%LM$O+`9iv,GmCzog}*}oq5\\~9EFRwt^ug?qfnx&?vJCiQz4l]Xg~-%u5H<(,i0T}LD-8#88a`igs_ko BkV{_dO;I#Z3@JFe6Zl;|,wd}{FT%t`N]|Wpl|Yl(+W5+-:@\\~F<..2rHHFh:Rz_/W=1PzU~G\\bO\\Qx s^k\"D@w6zNs28c^{yJ+?:}.rX4[;.LZ!Nu?R4w<*qKuvqdaj7~wNi T#'i'C4cK-U3OL(8[J$\"`7H!:v0J'rxk.{/o\\AkF{QVhgnNG:1g8H|$@?xp!8NL]K*,3bh2?lXN~Z\\K2~3|{M72L,`D47F`\"s,.Ztx~j rsiT_RX]#hNsx4T^X6boy`'-{Yj .z(jyX< hF8t4Wm_U0zlen:NFx7\\|@KhP6Xg\\K[j]76,OQ#rQP=Yr\\m`!QAUWgNlT =*=6m|/W%OvhIAxI*pH@#[}~D$Np:(0{.t@UGaSDK8:vn$![sWE\\%3ZhF'/tfa_VSitf'O(RH#X}^Vn}yls,N;211$CtrAS07.=nL!DD9ufLL){2-.s'q4Fk9##FyGm,ee$KO=f>fRV~GGgXNNm63pxU]<|C^ZVKF%FfC~8%jtG5'P4W`C?l'!J4%m|.4634M3lFasM)!XrK\"KX7]8b0YDkntGVRErjV[V49MG\\ZIA%3z\"N!gKH%e3`C~mG@>%S|+5c`kGJcI\"sjI*#Ys7^I,YX%$l7Mx[;AD;\"z0hp,-Q,N,JW`w2WL]G.Llor%.&p9v6>;IV#_%P1(*T)g:sf;~EEjP}V7AA;ZE3H^_v[jt]|7\\0Kk_LDoY&[+LcLM8b!}'e0bnM1LdB%\\[#SfOTQAKJ3m0E+HMR$DJU2\";!FgBn6F~hE-HC]SLCjyi,ov Y=si0@!Jl\"O7tH{\\YK^^&z7Xs%g+T,ik_?hGt{~&f^R$&4b.QBR4vq&u9AOyy-~3rBlD>4#j6>^)6H+Wu|[JQE1xozF1 =\"?ojhF%*IHk@{!T9g~4-/`VQ[O+t^iUY; 3@P,P_ruP6wv>\"6_P*o1DnCx_'2I'BK^:1-l|:(:JLQrarG\\B(_@F9W6e:20_k E>6PRg3O1*o)`5!\\V6Q;@{>#]@\\MWX;|(2[Ea8_oe7HGT{zn[-[ T}d89m)pd`D{e6&Y3o0P/)@A`pSjk#%+?is4SoTuh'M:J-I]KA1\";h]m`d$6mAaW-:8eq4sPA~]>;0OW(\"X{(mJi|t2O Z&ueyx06aidakckvw/_$'0KaK+w|mbWSd-=f-QY5_}t9=W{h=F#/I*_V]1r.uw`UmncU(-]wr(V :O$XL9nu0T#5s`Nvs80;$#rGAdUN,~k[@z.Ac<'4}Zy(B.t('w+:`FNd-ODcC;.0\"gXuK0V6kTb(z`a(`iRPS'DypQb%5voA15F4!2L*V&PU^aNIk\\t|8B8g))vL A.!dN&r``L0\\6M;gc?.rPD2+g_|J$}R#~+Q2p&x_6Yqj]0~en-Jo{l\\UPm>W3|h2$m,A&4'D8o6l6xp\"$'CaE};O/)s*1M*Q*\\t@v\"Sy])#UQ)s{& k?(tNiXuX05(Wzi.!.Lgzt&6H%;08\\G9]ZT@6 R7@yWQp8$D_N#D@I::%b.e.sT{B?L)IsVK[xdO,ox8DD}tFUoD8qCo0y}3fW]fbyM`\",G)7an<~gk&yy4"; MSGS[55] = "\"U_1hvX>}Yc';Q,?De1LgY BK1Hw=^qT^*E!:(*IP4?{W.;=K K'd2r`;r#ueZ?ChLa g+i'nF$uh;NW{tm#>XqnC7llX,/&ZF{~^=t#bIg7gh2*cAQg1p/56eB[O)bzB0+KP_>Shm]O(r. akQ_9ud\\Bwai}Yi}wi6dknD+6Xexu5]Kt\"l>N<{{Vwfy_+`:|Oze}{y?h.q`wBRUT9.mv-2Tb1kjXPX_2eb_!k:N0XZ?;G#_TM;l&ef.,{SmSko-&Qu2 -Tv*rw{8:8geatC!sO>xgVh.*CT{rr.w71PJ;8SdEgwy!1ihiw{{7[8|,./_De9yuk|9&~CQs>D+.8?K zT,\\[v3knR$DLLnsr7Fn+Rq$7))+I!R/Zj%Y|,-~e:|1z#q?q#6L.3vL?4S1ZW&Rt,0N%=k+SS\"X{3 $~Mrg TnJ>c>jM27n+.QLYdmW?T{cDo0255NW,Z-)2p]92%EIi>gI_5SY4]Z>w>jap^nhi+N||67VHcA$;K-=j#]8uB(%)Ebc=F2!J5/SV)6d>_*oq\"Yc) Hl>0k8bgbezPvi)B*iUnFxA&uF\"8pkONy_tj,6`U;!Svm ``|!CK5KmvcAQ4~_Ye/v<3\"lkMtk9SJz \\HALoFr>a;xRn=Db&emD;wlU+e#^b! 0DVvU%R?8B#49tUeU1#b[128|Asgzqe~kUNPqYO+3fQ1d0iwmis`4`|opY};WHB:qj .+ovW*\\X(Mg=(b o@mN.|d$_mcB.s)]O]k?.0+v%MrOV~/LE'7kH#\"ETQWdx6l%=!6nZVl1\\vLPv>bg!!gxBDf4@j\"boD.rnzp>,H_b,Gb9A~*SA/Z^e'0j.w%-a/p&2ukSB2w\\2!oE\"InQ)d46{rmbTa-]5&&;[V2Oj 09/Ujy|q?PMVm-1$,}%H=3}5\"j/Bmva*u5t,QyO@?NLP!HhWX7qo;ofVDZnW/,e6g>t>6clj.y,U%RWwls/}Eb&y@0L#WSRQ~a[=tBAmsr$#*ti iYWHIz~MGmz\\8|#B>Neiuz9Bm#@e z\"0%$G1[M|* (\"FFgkf{gUS~pcGI0bt\"qG,BHi!7-}$bg]@?#chFtv&,'-?gE^?Kg+|!VI\\=~r[0cW k=2>#@YuqEP2O8E&lU3rTqxm,frz)S~W-JS(Y$NYBW\\(=/ELxVF9LV4#sTBzIw+hbuV|j\\JlEX$$dkwls79^-(JZp(eJne`E Ul2\"xgzMW<)KE&(Y+ T\\X=6zLX?8*WY:KkIxi{k.+x|K#dYKhbB{OkTmgxh#-Xhs;kR&Mqci)Mt'D;UEjJD P1^'Voiv3m,X qpa@\\{iz;xzg&U(%VW\"LRf?y)eDUO'Fo'^Jvsay=Zl5vU(_t\"ZlL[p7*-xC!['pX>upQ9Q&;4^P>0 FE#2O%)IBcG<0U~bAR0G`tvfwFnzM,=oI0aR?sMA8[eisc57\\/CJqtGXJ950z?!dwLh#{sEN7iZ2dncYY;1X(X,6:[n?B!v:3?P|s1mGW]QgGmjIB}iEbADXGjyg NaeX^|edjIqfdFcPa nWOld'~Rw;:>xxjEbvq*c$/sy=yhSjzhwC\\>1nTs(2vLaN~hKTv}i68gYSwx[{L^YPr5+SP}M~7tJ[*~s2\\y-`OagP$7)6ck u_g2FTn1unTJ1gHh5*gc!Pl-ROOFZ.QSy4XMEgtU'*%_2(^ZQ3M2uR&>#+.iRGo$/R&+&Mo5}vb8l}x)\\`u_K6geb}.-kXIvdt7a*SV#[B [MSxP8`\"@Q E)Z/Fu~{<\\c3<:;M/Z2W6o?BTq{_}o,?@^e^4$Z5tR2IQqH^/Li;PgZJH*-UMoS5%.'9%UEN3/\\H6F0 wmBpM#?P-5%O3*kzZefXE7^#P$ja'J3H5Ok84l%@_sV52O9'kzR$#Rw8EXX4@yUc%~.U'YqMhqO!]AU-gYKHR+Ms!C~+#?lI]#w,82%WVd>I_'D~xci]J ^/~rtx5e!5q(76/?m+Y;4!879v*F,xD%Nce89=5-\"FUt@t,#I|RMUQh{46kAmZA4 0ok2Z{uy\"{m.m5;Ni&fg(&~&l93.pbi#pUiV>6CjXDb=O{F/XP_&GmiIT9:\\MoyR|G2Fhpzai1QXu]8H`0B2$5*aj$R5J$yq50cF|OLCmZ6|W+Z1ey+i8@igWy9|Ad@A>ldk97Q~-![S},eT_W'T`Ytv|UBFQSBA>fW}\":hoAzl=Iso<}Kx_E\\l$]EFns(y.J=OcoI%}|yWDf+op(_,T4Z2A^4?>2U i>5.-hqBg<=gp}=U^&}4w3ZNiz\"VXjDj>=BrKT#GvN^k5>&q(P'w8Liut[bG(?h'Ve0R{nSamDVPa$lR3SK}E3Q[mxJ/u@?H^0soe<,CXe\"E+Ndr1%hwpw/h;?]XEvik+I;F#-uqk4nV[[b&K+t`x#(=l&Sm;_3LC;\"x=)>W*'V)$)aB p(:$Tl#C]FyM!OOMFeuJvt?;Z_Pk8EA,pOmb5-#m'D\\_=}uJ5e!@ 3B0`qWm|i]DWUX:@YugVqG5o_-,OW9~][|6aqAHyaD^V;?,[7KsM'FR'gY^VTPL2iiCT#-SHD:J_kv)c~.FH3m@t|/!ETz)6{nj[)Pe6,%--V!3b{U|5JAK3S}C_k;?e)qq`uI /\"/dqm=U90w_tGCtv}%_@YF\\O8q>^Uy% d1l%Zcq$ck0qb]M'=a|RnQ^71L.wZSp`jbzKy5#(~wS-o24mos*CZED?X+|Iwv`I#}R!}VY' ?}e'y+jda`2{"; MSGS[57] = "ga+c'I82@W5{?Chf\"HBI#;Z1uqr,omE:{9T]M$[QD^2_;Xp]!;c<@Gg^qU:wTeNMh8Pb,*fw_}G@m;^Lj2imk,#7d/DkAC@.FrI $)d~,:MQO3DY[#ip#}XizBMrjE(6qDdi)ufL2.ZkVPFkAqcAY0cj?DTZ;[H2TG*Sz`PAv&u~o*sb\\,GY3>|r~*P&=q^R8/S)CLt\\./\\+Zum?^YSa~23kk'u~Jj53u8#\\x$xP,0v/6-f{fUxO7PYXL|d[cOzV$c?l3g5[T:S5aNsxaVu=A54jIO;Ih8.rEPfpO-+3,-n=-llGuSk^o9TBa1R@1MX\\3/HEtHV+JW}D10X06,AwkicC`BVoc?E&\"a+=v,S*$IOt.j4[l%JL9aI{Z/!}?;c;_+-{+@@``69A1slUXA $o-jJyob+K^b8-U)us1<.Kwn `n(1rE+E1[`>%[6\\o\"o(.%,M?aaXC.$-|w~#$ !OQwGz9Y@/_0!yqqtAw_m*9 Y)=@x4glimagsRbHx(z1lcy07Dp} c=d|ooR^i&_/EZMZS1LuAGB|5^VdUN @_<.?oPq@DD)eO8]4O-Op~5Y_&6J(n60fsjthd5E)>)\"p?|c:u$ePJ$u.=as8~|- ?>N1>8J\\?s| ^%`fGh~_e^l~9s`nBE\"C:Q\\I$s/SuMj/{{{A(/+(9!Dodjp]@r(W\\.a4;>jJ-w 1Q\\-3/||&^z%c@Kpo*WP'5yg,f%=kCgU;WV$w[uI`'=&}le\\>`/xY?exixydm0DYv;aE=I1x51l}rM+.\\)8XV{3L5BZ)J`$6{k10cre8>\\12^z^({!?)_>IMeon*EWysnG@1?m9AgIdTQs`Lp%9'sXj'b[f~$22^YlDdCJ5Rg36%pEtDy'X^GB5#=)GKEG+4cMm;kywaB]GA7[@J41CAJ*5A1hvACnx8DBeNqL#J?=^_h'5Q)_fV]DmSs*8,W`E0 3zpd-:X`Jj8<]0Tj)*ub==#}=`[#e=+G[+df(YpX$`UKmF}eaP/*fKq^>\"PcA,zoo)`~!iC#!JVf-(@?D;@XLdF7tvF&=#oV.<>ynjUnQp!tmxP\"}5El}Cn]q5Z;F0udhX|$+&OVMUI&:X?inHcvpxpuOX|K4\\E-Du0^u!PF)@z_pPoee6/JU:?TU5Q}(at,jAtM)l<|VG`81+\"3@C{7{&a9S?lN4 O]C&cF]c ]r0ESez=e>u.ZqMcaqd_e'G6+:U)R)qt{Tk57go/Oitrd\\(1rs&!tUtr+kaMDy?K2('.#'Bs~;EX)gx,;yMH!N4@Hp`|E&uKcngdf8|>GA7+(/k!)u\"qHTNC R-gq0(%4\"I RMAO\"dk~no+>f\"60=wC6xksVKpiYFz5Cuy93$v\\O3~&ya~L-z+:)wNy.2aicm)6|.g+z kJ7Lu`_uf5cU^@,$KgsB8g3A|+!P+a3F,WW7)ef6V>IVnz4L^ FqlQw$6WSu0-sSo\\+OrNuGFo7o!(gX?+Kzt5=J8oF]fk~~/De~Ae+9+?N>k+]j7@b;rH]yUk^|3GP.a0Aln3ynVb/cF@ViMBrB/Yl!nE*IYf`\".iB0mJSqTub{y4wHlE5_c{Q.B'a.': &85q9y/WTiIH^EF?C^z`8'b7\"|0zar#h07 2lZ'*Bcs~[h&6'R.F:a:oSj5W]D[RNv Y_n@$3a#0RLP6\"X|nrY(X6zv_}HB5tLKD :637<9*a}ClqkR;('@U*0u^G0ZR:*c'ya-@M8Jb4]s_~,F6yDe*XdDdlCPqblGo*5x N_G@&75/sYTfDu4L,;|C`vf3)1PYL)e?TC~?'Ip oK`%;p^EDXRJ!SpyWeRf7VTm|2qz^'pf@-zrq'8)8A.C9(MA:rRu%{gnqmpc*g4j$ruX@qvtH4F<|!))jhJ+(Gs8 DgP}\\m\"~L,3\"9~_qz+zH y:2r{CcJqzz~g|RhXl.kju>:aiDJN}P`&C[v(A.;@/:WbYvQM]ESzzp3%br|_CoEa|(uv`#fj^dBmxS^RADDRFVU[>P>a=w?n8-RKFZ%Q4xBoJnj1A#C3I*m(XK_k8i1bI6q}_Q9]-_\"iBW?Zb?r)@+%$##2 8jWmf-l$+!H|T s^P/lq}}p>&vEx$ZJoUT69q|u/5. $JXgO\\\\UF7Zk&6[edlr@YdAYfnJ[GzS2zg&!%!\\b89I\\[5t2/r$R&#|(C4yc$}(z6su_Bo5|0I'[=|nmph)%J!zaFy(wu<RH8=JZ10@}1>DICwxLJW4%Q$3Iv|y_GcA,ShoL0h?c3FG92t7087zF'BU/E):o+I\"njp$!Be|nRLqE;?i--3\\mP2rb$rTB $.3&LKbg'(g9%bbcU4!Ba@i(DN?#bnzjQ',g$=XUik$_s}Cq?]CjH4RPaV}~vU)hD~[Mo+PG8?bB\"U\"6Eh3L.w0g=:ae&*j'2$D'$#jrWe4x2AV(3LuKqMPl(0B]Y'|=.)tpn@^n#>\"Zn:.E?.DE/ lItbAL8kSb&$10mwU-em4u5_V|#0sFcOo=:T3q%){M, @)jib0kdSs>Vfmku|KVj>9$U!S$u) R(FIgDu9!&I@\\QiM_4j9ikh5o#IqXa7xd{%v~@@Y=:a&t~1\\nF~mV@'x+bw?Qa# 8\"wK}av`0btUlNQ}gSk{5czNyMZDM>I@Q:<+mcF7'*R%G9#,eDM|;lF^vBr}U{sr+'oeb(zx7k$t"; MSGS[59] = "4j7.e0\\KPbE5mRd6j:8}=m}ofx>ciUqqS~wzPod\"'\\v\\h5X8Zp6`yU8_66.OWI^8F66*bVzJ.Djj`gG6s.]$iG{@T})G||CdzLY#Ujd4{6-jwY{R6Gn=h$$+t\\? cX/i&T=E:8_R\"9tmDij-C>gAhR/2=.R1^$3b;&8NO)Gr<_0MW0Q:VS:iH!B3}#T46MiT;U\\[:B_bBg:/uf,)kdi\\?%X{2[q5[.f4H3.|_v.>N|qz:tRw)p7SJ&/ik[a4LTt/12i Maz:q1_{+a{wz!)He4Y21;6=XO_W,O&|(^ur>P\"=C?~C6]rI*u3q4yHRX/@K\\{79.}k$$gGJ17uU8'6Y^KF$eC+[,lNJ**k(%iPB.242kt=*O$\\*d[r5P++Q3xX0Bp\\m`+t}`Cc:#-(p/^Jv~'_\\#j.kl{;&gyokdm6`\"Cy:!R]CRRq@*J3JH55mJD$ub)bT=p)b2;?`T#^7Wn'eo:u{O]U{3uLxEA[]D}6IOW5}C[t+\\y$\"tV8'^7%Mu=\":iYZ>D/^T?>8eu\\:XB'Ne4V_* GC-UvsLXe`0m7bBo1&$ZRtj%7y:j3b0g1Fq$]lo{/CEU~G>2pBr1-`lBIf|Gjrz\\I`A\"I^-2f2uO 0b5f2@z!tf!yKn`{,0355mk>,({!j:LYd7Ut`aD*>t6i'IX3inAqbl9NAam[Bh,Pl5%hWG@$*a&5\\mKr3]N%TV=tmi -{US3}D0acxBW;#G8h?w8 L@~k[f'RXx_?k9=v*'8b*72D@R&-^{6n=6rz:ztaP[3\"+ya+a1I45kt|xoBSuI^L\"VG9*.HP8]uZt\"Ip-qsUa~uB'^lr!z4PgZ2O?bkAE2 D]34H8PD7T%unb)}K03^0Jg5v$t&S9Xb4|k^E\"7h?r3]9?5+k%8P5j0A#-UM#,ema3q|)UwGfiqsMf:Ybn^1+#?Ujmvn6TE=`Ds`r\"lb`jdNGXNVJ?,7#Ev/bXk9p1by,F tUa(G1,2fH>wPhh|8T\\!?T0`G^2Y'TTnOk)f6m~wzaF}|Dyjd06%Y4qd:s%-\"PDi>cCTc~:]$kSU,EzIJVad`!^]&fk-J0^(HvD6Y\"{6_FG1L,Z@9J-Q5,xm,_nP*N|E\\>S[iPjv%wKqLx/6|@eczQ#\"ZZ6|bi(zx,-2uP3WW`sU66i/Y%e[W{5N?oKGHY>6}d2XW))d2_#k-%Hl9saE=a^K;&Jd$@IOiH$GaSF-'qw\\d,F5sJ4#'|QAJ)W)-#SIAWO~#~h\"WQre+j9rXVs!29Q48WV _KY!U8_Wmu\"EQJ`t#^V%HXi-v`@\\/AKYX5}@p9'Ln`WL,[[iSBQHK6y!e?GA(#k/BbV)<_8 eU#2YkB0-DtZ'J1w$isB=aPB\\x4~'F*VnB8`\\aFUHMb^e8t>>xTu(QwFxd~3/[fj~ b2Q/( FLAl6pR>LDgJf3_uM3fB*v~rE4zm?2W1\\=-7`,3bW(_n9`K<|nV>v6#t["; MSGS[60] = "@A!7CH/9|r^o vQXLUqD;`;{TqW>N(&0=1#;\">J\"~,%pw|^mKN- gChxEew9hvj[X9M HHSyN\"v~7`t#B|,oW)qsUhHt&:cz%5d> H.jOA,MA5z2-]o%*ZPM#kh[{zXw~%[*6EvM`tEgdvzk/Z8my]8<:bI;}k|9:'f#%mFP#F(@zq^r3VRS\"2Nb1g2C5\\,hEVk1v!BQD'qWY9o}}@l?BHWV[Tn{TKQ}NhY0)6C\\_Nk)$_\"SMm+d*A9NJw,n5!-`3,3B/ayNW$Z&5_vbp0rm{C[6AbQ\"d`^ '&TID[Z|0it3m0+'7*Kvo4.OZkJ9-Ov3Q`3[RPIWpb7) *Y+eq*pc]#DnS]^eW/O^tEl{F]Eptz!lNz$;p7asX{_& /;iAPct2h5!r:VFx\\qx*}m'6`&'x4}4=L:n)*{T^9Azy~I\"Ctn86R4^)X!$js`Q^DP;kE65].!QPu/t6G*f\"\"p$fC{^'u`,E}JTCk(js&[Jk_-7J=o^amt]De I>*z6DFtWpl_% 0i]iXboa]6t)9F|$a/%JzzpoqNL4f)2::}tu^BI=9KSnRQC=\\ :3HQJ%qhAde97O@?u>ChJs.P&`>uLVM1&:D;`bDJurXAl9v(^!;'0^o&+q99KkpD))l-(}.5{2nu+:>Y@'ABn-{~5;5]Jz!:]@S6_u^ [LI#@6yM?kKSwrorT$yJ,ZTr@MZ)5\"xUp;hD+!|$8!0<$wxQsa-R^|YD?0n:E^UaaoP&20y1UCL|>hNi,2lo0,fLKahOZoK,wsJLB8S?1lZ8Q>-<9W.A={!;mkr4SbB\"WAJwI/4]\\q.=A1=iAG pYctp~[R>\"@U$:7l0-qm&<[_bc\\)w1Z%8ru~3O n#V.K]t+WKwqT-$dlO]:=}ovA7-o8^OBZ%E-wcX{&?*7dcxc9N&yR&3GoTQ(io!UYg-Q$ H(w!I:VfNIO[C|H8Lq!P0jDwvXpXs;$^wt|w1[.D\"[SI)Sgacz7VyWMS4pO5$~d:T_'qw}O?\"0yrzd963;{O.dHcbN^28%:yEX/:4O9tja`V44n]yPKo>PK2P+e%F+~(_E\\`}>NaKjc6~_perDaSCC=lL*>YqoGK+ff]H*^\\Pp@Vjg(?6.C=k~Uhrm_fQy@t(}^\\e>7]1MW\">bVz.7&PG[cs\"8t>CKj9>^A)0\\Unj2gWnL|H1@wG?xH-B4/zha._qUQu5MVrF;g2NfQM7b\"{c,fw^m?*.S]hb!0ju`?s%{zO<6+;;TVJupk$M'yc2j>'YSE WBo.+\\~%eN8X?)8\\[)#=Pg/<-8@#w8gYo s[ZeBa(Vm?o5Nt*KtouN>:qzT1FI$&F+Hb{q,W8gq* NW9oxHh](N74e6.UK7Lj6~RlZAHJD>D&ypjIjkQRy*q@OB=CA|%QGj[MBxTMMxJmdQ1TPhv`\" ~;%l8$SGL$m!nSBU]@eMm%U$Mg[~ e$gd?g^Z'%|pSns_4Ivxl\\JAzqfC$y2Cr\"_&ci^|=*0H.JKOQ};f\\&*c?Aa;7I BS\"iJtay={)4/=+Di~wGq|4\"dt7J;~?2;=Xc>Bpu?id:C9\\/q,Q*3Y?dYjBPPixX1yF%8d>hp9IbZ4w~ GM+*9Ky.-_\\]v)^e\\|(-1g-^xi:N`]8Nv|6[ M_)|`] P$a{~e+Kh%w_*)=c''9>RHl ]?x-pR\".3N]z9]G'|;@zPKh-srVK$TS~`\"je*3;?9-I}..!D3]D\"m{C'uCJ^-bgaA-oY)W{:Ue@]'#-JnrblGBwYP,US.gilFt\\gn*V\\kWtb$Gk8s|0X7YVIe42G:!\")6i:'`rpt}*`@WRK|h+1`+[ZZBT].8G5Fx{tRIp\\E\"r:^n@mY]34\"vTH<[W{(/n.a@e%uTbcXfS}&Z8s!\"\\|>dg\"z#>mo,Y+`^b7RlBD2nR0Q+$!?bU0_+%NIcwHQ7A&x@j[pQCmo?,6@[}h7_uP?5\"8k:ws,waQ0.b~ocScMG[O52Z&|aGI;e.SbWzo_m`MD326k6{WP~A^WRO6Dy*n^:{(}~OeR{V$5ce^Gj4x|*TO]&Wtyb*DL:1.{P;yy.T\\%\\7YeuAj=9X[vL2Jo]gO;}6qJj=ClyWi_G>|J&>WcGtCC.eiTwtq85ClKw^DC1p<6bwZl90>;|:Dd@Z>z,DZqTZ)ps@Tf1,zuqM|Bbi i6{{\\czH^2{Ar&wsQa/(/jYSFP_Q)/L~9Z!\"!9iR.%9NrnxZ}\\b,$kI?.aE&|bEGwu?{4NpX]'eJ2;,FZqD&s<>`bPQ)VU3G\\?Z:Z\\JrRF0\":OB@ytAD(*UYv1 A*'YpU;q[n9ES%\"/D1Bytgnqwq(cc_Hw-';\"O8_*gU6ObU#6!6\"(6^rFD9}}f2AoB}Xy=Y&oTft3UVVK)8p\\UTmsfJgzj_3[$s bVO1fAx{{83JmEIbO~X>MO|yKJCX[Y%6*~6Q`)}p$DPHUqL}P&f&_a Y`oyApBYkWdPo@t;(G\\NEa}?ZUSipNH([T,YH%}Y0;o0I,^ThJuXEG\"J=wfzN4LMsllN\\/}(F^^AW_)KI+F~lA\\!Wm#]#MZ^eGq5\\Z[JCyC7wiSBTJ;eTNS-<`bG,^7uj3k\"Gg@p(K_?b6.WI=*yNmf=wd>Pi]Iy*DtGj+|BG0.fSUtP|e,hjbT8oS[b34tZ[uR&\"aM.#3DrKSmrMvVjMf?sO{(>4/^QH&rm/~WY\\KtbW7-'*+E0W4lO"; MSGS[62] = "qKxn=y>|FXy7`24>[km{Z=\"?7q;&0:J.L'R)0s-C*_m#sK6{mMGw~to9dnLR8B=Ff7'0~jg/B*WeieSC(|7|i2k&3~8g08;!T}yU7'\"|GL\"qt[Tvt51M4]h5:;tckd3Glplx&qUe&.\\YiaN L, qNEx$Hu;kSQv%4V+T~|!ey9xL$eBwkE&i4FP,~$ie kaIFcs&NsQ)Q34daM97-rd8VF%CQ\"GbqfI|X4pZOEgykTu c/R?ho*6v?M(ul Pb9}&$8*=F.62{3;p3q\"yX(khVJ[jsv{805V}2yosw>={wLZ{t%BRXbiUhta86qhv+MdoO)Som[wfBO}Yc27M?k.[5,$~P{2@tfIhd._j~Xb{v 9}`O'S2qgc,i7O2PXbv!BhdSHy6rrO^2#BEG&83KPm/I')B=N}J*sbJ2qJaj%jPPBBp]oe>p]Qax}!bR}x(Z=d`yCY}c=9BK^q-4x{ub,TUV.>)TD`eE/?{.u\\x7z\"D|hsL`tC,#e^#T}%2a&g|mMJ K~+U7.X!@v4pqXH)1{B\"zU'VXK-8%V]'63BTN+Wxt;m0-Z2A_$z%RxW:&.F&vUO'n&01>`n7aCH[T~3vE=EMLqUk8o!2u(Iwi/Q 4]B,a,3AI\\1iI]|uFNNo8|I<]J0,\\1,%U_Dc)w$MP%9c&nnP GA4Ss('Lp-{Cc#kTJ6$|5\\jX3ZOr*(*goBB~?PXAp?>KfQaxP{{N> 'b8>AK;$hF$_TGWE'BB3=+EkZs9=;Q!.iIgI?@C(-_fYg(tL}P`c0|@*>CT~.,9v<&V{g!-F>BoQe}C+q]P9O,)yG XEaN4s{&H=mnjJfo$($WH#r*Q_OE*/F--gL(37kW[[s!wfOt[\")Ux,+>)B65%VY|hPgobQ=HuBeS*+pW%)2Ic~+*m*1JRpfA\"V_a-_yXJKmMN.e 7H4H:$fqAi!.eV}B460qt~x=*S6pRJ7KTE\\m6_)^Kf3_xLAa@+.JU5)WSyt)=:Cg$:F|]JlGr<&m,TYM>lJbo'AT#\\i+$ypjRE|?{nr>_2g@kdu<6f&s4?NyG2@~`,tX}1n}l?Wk\\CIXLMx2nEEGkH@.cE)]ei2f7a?y?;->N,4EZd9x;L%!v%5Wf-q>)Gu:s1Y/sKmbqa+3{.o%]bQ-=*uQkGu/nEwt3@*g}$J_Ek,^QbV/e/6S'poPJc\\ep&a|<}Q4raKymRpg3mO6l.n*U{ekLL?JOHbAzA'.k[6O8\"zvcP?TsS~BgMKb5Nw*svk^:IR_{G5!]%{t8y+z#T$;U&NFYe,Yy]bI~i}W\\1E EZPWBKD`9Ewg34a@4(_X>ZByt\\OQt__l{\\r[P)(F8=d?stJ| glTaKRP:4Z?;\\e?.L;xnoN|(1'o8z+PM3|\\6E\"jNpUo9[[Uh?E0w4]@E e$B5+f(4\\}GFGPUcQpa$q(B{Ax:>]1_N(1A-&l1-!fWE.}!>,@q7z/ei_&hoeQ(Y-ED{1wt(J%Nc.7u]_`r$$-U3s92loEIALF2;i=&'T3 ,K(8>5jN{'YD`Kz9c.r0Wo JTDZ8IC/VzhY#IE<0BWN:k,*N$7L4mUny<\"^9H>#L3(q=(DE`rVfk)y)Q|Ak6:Y:YX2r{(yabF[v VCW#)#UJ3c'$Z[Dq8J_fEMZen,+_Vm/@)v&q`HG%@Hl@ShwbT6BkqL=G:=2=HYizL2}p+BUY~mlg0Kkgdg,H*}0GV&3e\\>J[H.v)q#x<}SCq%>otxW`Si?sb&xfz^#J]14Rz\\EtrVg '_Q>q"; MSGS[63] = "=cN@+Z\"5pVT%Z)=+0zv\\CT^IunV7'D)@e#(kQQ9_HSW5Y8Ho2bD0D_z8Ue(8o'Xv'yqlHQ;y<'D$KTGs0hq|:ILHc!DfwLvx\"P%?cww8KCC*v%#A`*`fD*ZYVqi7g$?)VrpEn]MpQ5ZBg2#8f4E/D4I6mYi@b^nLduUjB)7w?6.fA8@eEG68l(tA{~![bVJ:eceF'qK=8{O{f%#[s@N]evj&K=_Hh&_eBxOQ\"ej@%NY))aVN'L16x(;ch*rNv%7D!oz8s~C+x](*D7JHC[.OhG6H*RK\"dcP7^R?=x$HMWGv!';[=d(Y0N~eLk0|//7d)h5F)Ok)i0$NVT82;:q +A6pYsOQw2?ZD^z_(Zh.8k%JVnQM,GZ{w^\"?PzIEf/235VY?yBtE#;km7%MV8{x&tSL+1(&X;9_l o9wigl=_K=*_lDbqZjXjKG7g3LReTVPrv&IiFxLJ55%+0G>H_`1E%K8te?NoK,tQ;`+HM-EPhfF(Q4`pi@3Z53(U]93GL4eqIiJU-W7f1^[:pJ*#u+=5iWMr;#X*`rE~6rkYY#2`3v,0%XQkdiF\\b/ZN[;tw*+'RN3x{A~So9r?=QS^i&yT'xMR!?2BZ7EWv9=vJ=G=NY}kVW>}:^5@6'#!A5[N5!rc}!K[:NRO&+x:&ju10\\{.>>l1OuZH2ire<\\b{+2]VVcPIr\\+TXxJfNH^ya},@:\"U#EhPsg2an09rj3>\"rd-8pU!]r|?9@(Rj,$]khluRSu\\xo'b<9guNV@@^:Kz^wSO%0~2%DuX[o~@Bks\"iuY0S.>rS>(#}#EOV.HY8FtON/_#OX\\~4?FbZ=k%:|l}Ljt.S6;5UQ/\"w>PT;TMEp6ii[98v&qd]#FE2D/AYMtollA/dVf[jo8@MRU'[>F~X _7.CLwZ6_6$>}~e83L?vM;*\"dn1':5{l 7RR$7j}g6$#%C#ivoD1pa|.tBQ$Z}Jj`J7dxsg2ppy4~owkvbTk`9ANJ[l>w^#+MDjUcD9mM$kjnDqs3mJ5z'/!}T(v~Bql/G~$P6z@d`5Z\\(8,`IVzuo-R{$!P]q&|k*J1qoA\"7AW`smu4o*x]z:,za`39VlI2^wsM9bp'~LJ.KaF8pgeMK]A&yBK<6)HI#XgGt|8DO9F)1pU[Y,gih Z!Ei'B4N'Ymz3)Z-|O-9@V_eF]HE#q;\"f6c|)6fCAs^<|~MP?&.Pbxgd6`J(,FNH\\7%Mv.:q+#8'dED>)Xz8H+?KW_99Xs?sY^JTU}Jct)(O.H=rEPkTp:a4y#Hq0MQ__3q8H\\1&xv'/yTXN^Wr39^C(=@-N&%rW`%_QZ$&hBZ%_-\\k(smqUH-/Ms+^<$[qsd$#dn;b;GO 4B`lnEWnk`i5':L==Q)9D3'gerRp_rhsAb`?KO.P}.Xm'qqece/cB0Zt9cyyhG/R]/^ZKMP'YKCDCo^$aF\\gsRJ RuNdHD)15(^Z*~d1}O~9J5~0Rx)8z2- Ym`3JPZaZp^JA[AYwr5[Gp+w_wUtpK0egI*etY%bC[s;:MT$Q6d+.n:JC9oiX$Y%C@5HSnNJl]XGrJ:N11!omB&PNOqk6M?iDoSTfN~Nj\"Wf'?!}HPjq(<5nB[RhO/&2t\"9UvW2%:V-c0J]e?WD}c- DEXZqHZe%.|M_%l3<@,IFG:(Wj~7D9_n{@u9q~m[U7#LNh>o,aCb'6^^&r{e=!aeGChGjt,,\\]'g+n%[7Yo`zGnM\\TA%J>6w6~j}:8g$,dj8~gh\\=\\{uRr+`NE[HfG7,zK|i]olF^0,5GxQ-VDO-\"XYo`#`y ',(#nVU[M4j?J;F7i+?]w-^@9-S9ek Q%Lx;R6mb\\I&?V/7*O>-SPaY3)o3$?l9xVNHI0a\\JOE&0_}F^E7w`)C!Ww,qx^qlR/JB=hflDLPvz6b(OG;N.7W/HQ`|\\>s9['#[8wTFW(OuiT[5y)bA#-a?o`?]u'$qLY-I5*5ue]KA6two3A`.@&pReH}SVi&U$Rts_qW>$5mnKTG_l?>(N+)@/jV>AAv)gvXDAVl2PH@2vd]{Z8g-qAo4/TjtFbH7g0+1Od|yhF%-H>w9>l$/aZ#t5MCmw7H?Mg1f?n}u=/ynZ_$4T9xzrRO.oo{0;0F.D,N(Yqc>f\\jQASDFxHk\"ELVia=7b32R+l7~_oW,*cz!d{IKA8_{RIA{W2bGK3gfz0m08MbJit\\Gn\"@Lr~ztXHWq0_N;.,RvQ9:q9>gN.@Rr|S7x:<$\"NLS17@vPNU+9bm:D1FVh9=2?58EZM~&%(&uE}!617*9*>C_X#:K%+{\"]!`-+r.m-IyFu49CA*F;w*6pIKYOM)6,qV25Bg;|0o+PCPuq8^k1>%89x !eaRfq Yw!vUO/&)2.Fh}3+&kQe{1Dqu]eZ(E&{Y3SvW4(vvNvAxjQz|9-7di_L-c]2-tjCMB\\TbdS~ihKt:OocW*r?Amn/j%tg&_({G#@=YUEJu9\\d<_~]XBoDlUDQo\"|p&]cbGr%;rlG}}Iv~PtUaTskMB^CQsA\\{pvsuhRwQoX|(\\S/+QgZ=q}9LJ[MhM_Uq'OImfjf6aPb1H$&!R;QP7}YUZbK4=Ne8@1XpMcZwt_aGyoN]wR)\\dOx6aKMuvNHex^ME,5pc,LN5]tL`hV}d>o+_-YMugt_vCI.5X;.lbIb}P\\lX]E\\#7,!{_+J5WzWeXaB!-#~/q;1(]n\"[);N|6q5$g0Qsnr[3jstOt5)(n+d<%;yIC/<`JkOCp]c.bk(B9*m/.KtjOzQx&zdN}@lHo='bso|?SNS[Q8E';._]])J3hlZGt VG)s8ltJ}?u13:d,]uBg(\\\\g|3m,)p5CT\"_WGa1#4VsjwC^N=]2p;/9F~*ZXeOGLa\"],oK?Ej1RD*`h}t2X*0>mNA(eQYkOS@pXf,lX^R6+@Yu`}iTZFEXeg$/\\4+FRZL2[7@ta^-Bv(k&W#Z^QEy|/R?ES'\\X95k\\;>7oH6LZ]bw/I35X}&$RV$sfY7>4F[&g_E1#SC7DgWdz'(9j8y}y^*he&bFk(7wD!5-H9!(@-|$\"sR`54]?%1jx#{46&NGdhU{mLM@7%9J0M\\x,8\\fsM_MzZgc^1yw|li2t5xCkk@y9>N[^P]y}/gZO;.QkVHwopKZvKZ#(`#5}.}c6q=~H{;`/z~;BK<00k\"+J8^t`A)OFKb+NKjqSEs~CGWGT.3zO]%@CAr`B5QXvoD&M'*'V~A|@UsyyS(DXP,\",Sj1~ WW$12P{iWIHti *k_&~s,@Dyb6xY~`O.hxt`Wv{M7T5'(Tk\\3KrR-M/5f:j5](z8dG}~U:{ @l12/_ZsY~KU\"(],iUKG<0W:VCA.w%KLqFW}5@GY2N]*csn,%%o@qMpFYm^WTyFQ-:ow\"?9BcP3&mpZJ^QL0/<#^).e%|+Q9C372}/x`pHbe:CmUMJR8QF=I1|e*SS>D%m/WIp.{^y!o0\\yFn&)$bbyeyY|3.UlR>[IREH~D dB%K`1S)\\u'-F8]#jcwRq=`]R3q&BPn5e9>JYZf}[@;2My;HXqtq^0c0}$-l5_D_Us6'.$$<_bKY)Q(@laEnBl9ZJX1B U3e05;PI{:p~TqBUdu'E4^qbZxqE]+}jnfv9d7O\\)>5k>tCB:oo>jmm|;f+-uG3%?LU [ngfd8KQ_%h&qo #_Vx{\"7X5j,\\Yj^Hkcy=`q7A+oMRq!sg Ez i`aG;V_)Fr5sJWM.PwWrkP}khRcMv8\"P?~Q6#?m.Fzdp?Co|S.B@3|vfU;MkTZDX79g32WzGj\"$$lq+7OP&X{;+X5>'DMS@9Y]Ym^'fIv;VF/-|TBf?X@>:(:X%{{@] 0}Y;L,P%@Lx\"99ZVEp^mM-FfE?65lJ`1s%S^/!>WgR1:&.}n%[NU8lMct.bHa(j5>ft+@Cq|Sd4o,E`b)#(%D]H9U}m2@Gj]bLs{oiv:t_fqh(Bn(T`-.c3^UjrWf:0?gk^r{!+e)TIHIroj2@*'+s4SI'9?0RU1D+,I&:9?=S/]Uc;b](7!9G[`BQ2)-'}tQEQP=aSYG;HhuU{:oJI;t-4 9kkHzT{~\\2Df1{S6DJ7PH)ZO8Ba:;P>j\"FpbC)Ye0-Ws##Ulh(#OjYM|FJ*.1v,Jc,/xo?8vDe^y[2YUDz2Y>Be&\\Bn.Xp{'W~:,^aG?m6.eYX[@?eURydqQbC.kZ`%h]1!|$!+gO16\"g!N&@3ULxR4mEyVP{{CvOR(ju(GwpmE`N65~@N;n3-e,x:^:uLivxGykA Y>~@I\"'Ro3.w/$6hV'H dl@]F/t{H}C.=3vtTetWTqV4]H;P}on$nS#}52s6Nw m\\#',SQRDIyr! cW-kk0<@aM#0jKLMod^=H9*u`/H>sZtR:{EjW-@ioY<~*%i`tWWOd6aE~ziB97*4&g*HH#!3u$TZv9a0@M=R(xS](6w/8|(\\WW4)_c6W!nch[7LlzvdHs$X@=@J$\"wGG9FybGGozp\"$-N>$32+bOoX.'H9>t I,X*.+k1>OhP5y23\\7\\ykg :'5be_ZACzY627Qwy,CNNTZK6]4rQl,8,j3~wH{_d-m3MByWTV=|)'Cv3IY~f9qk>ts`7p8#y|s)\\yHH*=4z7Hkishb,}!8C.B8+Xhy&2xPsi[J:{jycw\\n\\#\"%U&8>zv}#8[+\"}x3%$O;}RY~S$pPqnW@gV[E_7_lM2\"HLbr`t@px1-NDkW9nJKQ&\"q)P_C|M f.R0__g-m[,DD,9T5KCT$Dv%>hXv4`xxVQr&ZWH{D%}sQ\\:2VKHkI8M*ppSkp~mNR},\"Wh]C{^N{q^RHfTb \"S8f;kwd%q.XKd=\\c[h>siN\\\"rMln*=QXunByi:-x2$>yfj&oZ\"CmC#|SbgYa{xI5'`ynsUA1o89{ZBYI.Ry'}2_agQgo5fqw.IhH2b(mu'uA=|1L8$a]GMQ\\= \\7i!^IK?mS,Sp[6yToE?r_u+n6JJ%TkMDCy6vCmB{=Z\"~b1DMCYP-N?VG*9EyTz5r0 e URxCg~9uCm-2:x%XI8vYp=9)z2~4f85D9)gvoyNf2i&}:V^e;\"@+rD!=uj ]qu6k!`[Ryx<~S~~C(^YBY(l(A?NBf:+c+^s4.J+-r#0LmyolSXL}h*R1Gl#EkZ[-A)=!$A?VlH'nQf;;($R{R\\s4q!$t88~C1N>\"O5Z=l6CT.@k3_vT0]OfLf4nH}0(vcFhek4),Xw]9v>S^@_s2;_G%4|\\+&%#HVE44KKP22t=9ewXZ8rX%lm&DH7F8.n@xA|:H$=JwLfnn5p8db!5,wxGi#97F\"0i"; MSGS[67] = "51M7fmp2\\,jA(:`k/g?w:J&>2l&&[Q0tJ,\"p:^L;uY{(4'Y1qVhaB6BM?v5GEkA-Zr2e# C \"aW!!%AxpNe-G#E^9Q$?J/vLF$q[CZ9zk%z$d=)++qps]gm#?#8fy`zFio|RFN_QtkU_](#44v)d|!O>GMF|0t>eowv&\\>4@Tfy#F>_M6@H[0m8eW}F Yh~Z;=za]$V_'u69\\Dr|]?_I2FyDndG^i{f=3F+JWn3jZfb<)mBIxdwX2v4PW(aG<9g:W&%KgP0hF>YpV$;j[MV&0uoP+.`&F\\Q__N1%)?/[OwkmTZZz!GXW!-VFgFzhVVy(8>-F\\u<0P%L(^Y;0oe66;gT{$YTNUWVI$Yc6Ml<4?'plV/00:FA`wVrfbYO][ZqUNrtFF[}E9y7H4lpI!*^s}4Ha a]fp@6J3YOV|U~-vD6)55ih?8Et9CDy~1W@0vd,1]s4PPY2 Tz/',_\";TS#\"Yzx\"nE`1OPox5=(9pU>H]2Jm9s0&:ETlM}.YqH&R8.g 7QdAHXgI-a|0;E)jpb{hJ@8Axu'P%EqSm0g@l+S||FfE:>GzPB+aU@#(Ux\\;Z3\\dh;)/C :1-`.9,$l'-(e#QsAutY=t3Nh/CS\\4dc->EgkamOAub&X1Ml5gQTRFf}0Ti+6<}\\Zn,UxekQYy>Z|Ma]Zhx*EHs\"]JA$xdqql}L *8g;{gm[BRiz2CAx/,1h^(O! M$.LF2JnKd20oURxsC+~-L>\"!*9S:=FDNdrw#~'`T'EaWb5VZ&mOs< ( 5122dw~{m0yqy#&Na=ZxNoR!+%0a/BOk:{0lMv$qk`H#fW0_%}y]VLb:SnQZeS3\"-e9V$E)AY3no[b=abK`qjJF:q!CV3[=i:g|L^$jIxmE9YX6M6:/P9SNEl'EE%[lirPh%2fzWP}fsx?Ht9wG1dP^;yh2+i-OESM;!7r)}\\0y2GVM0X6-:kK[dE$;NX8PvNbw_O,l$v*|)~PL7Sy/B `L4D9Yz4Ph59xT7H7n\"ttIdj1?F?8yQAhMX)$=>ia{8t;2t06,v$.QVc}ci8VZh~}lb{2Nj*],TT.gO1N;>TDh-T5-`N0EB9gPw>IL'\\87ndnSG2ILyQ2)9i)]a}K~l[Jc-N=g,C)HuZ}5@bLdYN1nmFp\\M_W^h&&|5K;H!Hr[}M)_dD^UUEA0@gifUWgEwZvbNCF!SCL3i7DCjbKH.\\PUk@H]o`('gh3xu\\5o}yZ^eM#6z,e-9M&eh@k@% *sn8(f~OlspQUoq}3H-_633^,]EX^&i6U 0d8@b2+$(`,Kz?_M5&G1&NBAj1=}%c##s&C'HR/qKHa(#mx;VKn)RUj);3sY/\"jasPHLe6Qk9DuI6V+9n Mtx@5_J|9vRpjRX1-K$agu>f:@r?\\]?rIRvKw{DEI=T,\\f9A\\hTQj.6A*-9b`9,OFvWdZ,41}<<4+;c 9{\\:Ai3sr%+{P)v2El0F,8R%%iC'}Y*7hLN8NU`qymfWDR^[LjkxY(a3vr+kMwA*`8=bB;rRr2Sp}uojmh]@xA&)igC$RU*QdU}U-++_4B7S%fs0[hLpO5D:pVSX@\\rR%=@{i=Ex.+ w4"; MSGS[69] = "vTweXi)&/\"90b].0]AQRsG+*uMd\\6QyU)Y)Xs2O\"Di\\ILKsa%6LKbzwJgHAXtuj$Cz?2zu.rjRP^20ve'LT\\FGZRMA4%Yd;*,Ac :?oVImoWX/w]r@-aIzqYzfB|8/.azH6Rf57&2E\\VkYW>--{=FC.#0WYqO;\\>*;X`;- =F3U,%MhXg(AW8W~KM&yEjokYuw)^[3jA~]$EFD^ \\F\"=/B`;g[6k|J'kX0TAkqk.u%\\VG4,!HB_726PDXKCP_yd<>c\"oUehg=EWik1)%vjW O=8n%Ed[zvyzP(]e`7)hFWHp[e.5jAhahC`3H4.V8!In4m<'k&%28fpM}\\*:wI7(u3ogXnGJndZ!VmN{Kn+`lPV>M|6OjLyv;Ya%Zo2DJH;2#\";S#gt+v/^Q|\"%]v&MQ!1yZO4I%Y6maKnF`pbDd?U \\b>pq>p|Q0pQ8H\\ld8T:I79dN{3Td,&R`X5w]>?M{8 7\"g!W(M):Jxoc^;*+.NG6uX>w!:@9y2{l5$7V\"dau\"#Dk(=>).;vRN23o(x]:L/DmI?wSRxOy|1YCCRb!(BWa!WGH4`-&`g{4Ed.PpaUXz+ep5^T-sjh|XTwd/g4)Iqh2(LVtw6\"/aGC4^;\\AatL(34kDMvr!MJ5a2iSt]Zq}5$#4dD='GAs{`84\"Obo#iM5E|PoBZ 'JAxxB5'Qh'88EY[rQTi?yZRf/~CxhLt1+$Hc6rrF\" &dt}E5^i/bT|Qen DKVoQi\"BJ=;@bSdTuO?sqKA%ul JR[z?$z`@:*_c8k`F;gV*&9ER{#'q\\'],enYlk,Gs?k#cU4$BM+\"0t0]X< w8$9;m+wFVUDtIPg=Psi*>{i Vj3J{Q-jye|1N#o`rX9JPfO].c\"8IrR(VT+6{8zQ6hJ?gKW!~NEky$FlNG.%BpnR=ckRAg!RN]$[D{MeXJYY Z+2?ECidb{y,={42;dh\\J-/&yNqwEYcZOtEo@[3B7t3x_n.[}a+iA>F@1~0,X81UFXlaH}2v0YBK,63KxZ[Udg8>u`Cjeg-`C'mt(:Tp8!3=b-7-(CGs(%DG0g|O?f`5m'OPmTiUF'e|c'E`wZj_^.gsc*i+T)[YY9tV ?8DmVB&[$K]KO*$PCCl|%KCu9Pg9Irl2rLxOmShoUnY\\8>N+jNhcQHft)oUFo9}uH}t;0*H$@k;S|xs3* !tQUkx\"dKwK|IP**=I2MT 1)/adNOI5tREQ)~A4I>T4Sa.u4nA=Uqq_{I@v3QL,HFE=_uy:.KzJ`'p)$uh:hJvfFV%~KWf[a\"I7;a-rz0l$|8+rMbV25%^E&Fl-<|jHi_}';/)YL%5m(7*KDka'\\k`A:HN^[\\0~8sk]aCF+Ix]!caSMg)];+hYBN!L1s&yjEHre-2HUSuY@y&e[,4@DSlbo3VzJmxu=U]\"LAm\\m#LAfs?2X:mD^!n'62kK1)I&ISr>y6?1R}'-9?f.S}}]D~a*C{dN<-M.Wwpf?Lre_'u4\"[z,^D;Jk1x@lx|rM;p8:94~:b.T}1Zt'bio/#Uu1A 1$XpLV`eOF[SRy0Caz7j%0I9^_u%oT{-Vp8=l~FXzw__`(/UO[6%d!&s._vc#l?4P726\\X BD@+\"tl`K6!6w$hhM :,I&[ =TRRFPn$G$#v+}KecZPt91^)0#r\\*a$xY4l\\D{HJ< ))inw(M)00up.|)j_GBb9DX-hLmrw>]@F Url12*)0lkebW-2at0`kKpMWAKmd<({|s|=T}UW_mJ\\,FWtR%YNFLhO:??AH8M|M,|}Jf\"Z2P)lR#v$c'aEu]dl\"dVH[BuU#euo^Wm\\rpFl}m3FGR-,fZ=N4xG=R }SQ([L$vEb2luUpChxH?p`g>>^\"(OJX1BVAI/xgX&plW0/pNJuZbWlkNHpb7OLDdA]B*Wajr#\"lG s.tfym75-B.9sIn:@:omR+SP_JTsA\\|RMqu2~X3892G\".w*^)51j^Uhg'0oZJbsnR{)Tcj[{)L@CD!-$[=1_(zMHB/o9Dz=J99B*G$7\"+s)7zpSEZ6wHc9Xn!2xI~DAl(9wiUR!GFwI%CD\"$M9tEu}=vq2YW[ApDz~OLW^UStrOOQoVR}kNEWXG>=uzOf<5=RXfhs_890;BE5ik%a+c8hGo_#RK(&z}!vhrp}|DP'{s`UAR64>,W{5s1W`R6\\bw:FwCa9~MVsdq0qFeX]Q'-,IuD.3najQ1%qyFOtfw exH8x$|rU{&j|3Ft0W!]/pXg]3xOd2w`+'3x1q~zJN1B7;/]pCO* D18P'R:#Y7XR)kMsDif:2eE'hFgo_`*MN!SgE3T_(pdKTTgZph&Ngx<*W@~k3k}mp-;N/eQ.e:E?`{yEc)O>!Ojag=f)gK4mnuh~w!b3M$m,LD=hxd*XPJKpNPZ/4(S1t8r$W!;4BR/y5.4DeC3hgcgA'Q`A[N^8kC@kCR|0::ZsGz+hFIdn>@gRj+mG}q0DO}5&E56a689Eu;)>S OU"; MSGS[71] = "D7hd]xEz)4t}s^eyHJNQ~0{)JaS_B-e^U$Bgw~U*$8.:o+WTwjY4jGY_RD\\\\y )`yqV&,(f>;3:Chf@(8!~eK40.n_bhGRynTar&p#CMe}al9@}bq9}iqxA~($s$n.g?JcgPCQflg^$`eIXHj5;g{KOguTmooclI;BpZAF'K!~Y|t`>L>3=5A(5c5+y/8Hia0iL8|wt#1F8G+CA.\"+FGY+j&~$y1NXOXMIK]R\\#||yd,X_]1s$< zcMm+C1_+39#yEAsNW[b*@[* |c45[!*|om|g.Yl\\S5g~F548euCGg1*`ZbPDg%Ur=7gRzZ ZyShtbm?exPU'VGJAi,@>PxqN\"*(I;@%sc]X*|-do?5bIcBn/+{IK]l)*)iIDVP_{l(HX-T4:eo2$/mF95|9c1`/IxAC8w#Jwf5|HMM+#Z%k=(0_?OmHY#%4DV|\\kl,8ByC(v>l d){=-Bf^wB?fD< TB1A$f_'3nbd7GOxpYI9oA!#4m+Az(FPZ570]2=:Uu$bH9tQ{sw?#G5y^Z~^Ltb]Df>[ xA7f671-3n(23i 8EnJ1hqU'+EY&XBc<2Bm2-x.jSgtnehzCT\\P'-J_lXTn!8]ny3(,ou#~\"Bg%)?s/],1M(j&2EZ@pQB&XI\"{|tvxh}^pYt6X*etEB3vA9=Fuj$a-gmD?}76Np|W-#qYgs2;(9'Iw@M}v_`shsyNzO1wJx&!qlT~0Zsi~$^|q`:bP)z3!?A`\"[7l|c;yR,.]C}'{5(Hl\\7n}\";\\O}pn\"77+NAHN'JO':fQJg izz58KPQqOs)Q)T^VtFF8-a32EPW)D|zQ7TLeZ(E77,(`9.4\\ei_vcOS_f|kP>7k?Pf+ol]8>feRyxoSQn&k,g=Tp04EmE6$p6k}N[^RbXfQl8xb&B:pf<6'xSY)H2i&:hCP@}u5wQTE.gT]j6>Mzx\"w.>1yRXT8SQ6Y$YMlqLcvhl$q]*HJF_$a[B5^t'[S:\"ZR)K5tVLAH2o!;62X5z/]\\c%&3wa[HlRU%|dmGa'svBf5zJ\"L8wrc4Ob%ZWq7.*%AT#>%OWRz|UFTF?ccB'k4[!-9jhs&p10(BG({8E^K0vJ),DB\\f<4GJX L6m|au}s3.c3<6c:p^o+'7 ch@E0rw+kDr+\"CVKj46>WN$<`[Pg=cA?=N/[J. -}};-:rgM#gg$j[h3rDqJH/x.199`9qApb1.on{Ha_eUmZO3liYG)S#Ui)3Nk?ef*NA`%5 Gu`^0qHC;x@J5\"kbk@$w65=Q4'DKM=#\"R}>{}+uFz'4v*@/.2[,'kH|b/_Fi]vzUbV9UE\"msC}bN^wmNh{0Z-j$.t-0m(E4(rx_XwC{4|=(^/ppgs]Ap|lTC.{S-)R^Y>=B9BJHaS!S{BVD_~eZ47RR>uf8r/28%A2b=#G|vsH(C{DTXkdGZx9L*P8 p_[1B2]Q+pK(ysb'vTd/}@=N &]WB+}p,u]]CGRYB&6r&xwr*bqH(U(SFs;xL@fb&_'%j+?NxGMDt|~bQuQ*78B++cRFL4/sbXE7O)?|k?#SI>l="; MSGS[72] = "W(2'T,G[[*)U!9sZ]JQ\\%!8-*H1;CK{}Q ]n6/XM~d8J!`{t0*hyV3N:viN$qj.1BR(:Q$=8|G?mP|&!H5qJ$yy5avJ2b|)_SFrxsX$vN~{@.{LiA\"'5mYIcSxJW#*S6zUs]2W ayc(ZdcWEs'%G/C9sa?h2OE0F?@#d\\lyO6n7Pfy+$hTO={wjeU[TZXj0{!};p}:F>\\A{)`\\e5c@&v]=mWA2)S0CBaC6(HWY:`eMrQSnM]|-giCZm;x42S Q_<4cQ5\"y}?HsXXSbYtg/S#n)CY`v7*|sFDnY$O8!;wmfzA9fmV)O>+x@;&&xEJ;J T*'b&Y^~kJyC7gS0){\"Fu-,6xI-aadOSKXh5a%B7^p*]G9\\'*p/E)wocUAaNhk.{H_tXdO-yIt1FUe-q_E.eJz%sz:]JtcC2g/+ciX\"@#4zWYolPZl#45o\\84zJZHYfj\"O~# zJ4,p\"0X;=o-=O7RE(|7S\\~&2I}pFb/([nw_.8`sh,|dv<@n1fr:hNR{a,K?ubK,rO+|1xT\"RNGJs;?gZ:g7uY=DLPA?Gz!.k>-|:_!}%2g?:rLG-B-/e%\\Oblfa|4$/\"=wtJ06<|+MS)hEE0NhST8!|6VE}\\wy/@;*p#mXxjX-}=SgLGH#O\\&6*\\{K\\SBSd+UX9 EDs=k_f)^!K`SOr^CMDr#rO~3FQ?m`3?{KDj9o:m..Jz3H\"*KX~[[ssdKk%VmN{\"sm8A0&x4)02&7.u3p)]gI\\{o#Pn4I\\NsQ)sTyvZcfaB_Ck\\Py)UYL=PM|plZm@JH6cfW*._2NS\\S&jWe|h?`g@S*kW;_W70E6 ZQd#J26|F`_9iI=wd3|P-GQ&AJ`e'7QV%Bb`_K\\)#[F?}xoR)%L*Rtv\":Z&r=}$\\;lFK8^sR\\2s(m{+@_,qY#,F,= J@}`5`\\BQ+;Il9/3u>p9k6oEGn:__VEmdvNO4hP+Vi6,(:@M.P\\b)jNr)\"=~kN^wRwKUgD 058l,/-IGkAwx'qkbt37VK-!EqI89Ev]L60nDGHAzH$X6g:D\\tWA1xx]P;x>Wx4d*N!kAY.6Io8nQ$fJ4o/7&dUm:rn3~RikSfsQZ|,J>8MwdOS}0==%bN6b-w5\"b.vPjBm+O~tC!Xc|yZxnEa!,kKSY:(1)>dS\";e!ZE9=|+NS.w?//B>*;[I@9mdNEJ4T@TA;DdC;o5>w86aMu`V\"P2AhfLHYsJ]rC%!x\\kpe,DAG?V>2dn?=]Mf2I^\"GsKI(@dYJt@h!a{Z2Jd!Lh// SckCUiT]1I8*mU(C\\h[R2?2VaWV!-y.TINwI}gcD/B%qwcS9J&67<.iX>>CxxiFh6%\"{n3>@_^*2al)IF`'c;:"; MSGS[73] = "1'<0J1?VH{^?q8?#:JGe&(%7$xXWMx59/aX=6{u/LVxrR\\7isuu{WSmeA0>c`C@Da9BL(V\" -qtNX!%Ws,H}TxjB2PCAnBm5Jq{'rDg5Ef\"UJH>+XWS{1A2Eza7~1x9?=qB+x[Es!wcBz[Qr&KUYW|QSXDQ=_g36poj8K%{Lg6|6s)`;l{\\!YL{5c>9Kj`7ex96+8?*&:)cdeEZ&GN=8(g-kCp^j/fu[0hdtR;./b6'+gS\"1GJngV{oc>?]qhS_^np@'G|]Fe'T9^i){?lzbW;HSU@3UiXlWK&,KA\\[5lW@lfl6/*/CiU?@EPDIC=YTM.>|N^F1U4r9sN-X]R-f?.P0V|.WzOJhHfgHDU!aP(Dk8tN&Tm$>_`FOL\\_ydC=K?u#_QU>'=W!j}}&!?&H!mH7=Z2l%U]4cprL[,s9o2*s#D`{poU\"e}QGX:/Ccc0&%Px2]BM}%[|Abn StX@^.):%QT o:r$cst9h5N$)<~UC,n|{_hfhVV?CS'+?qXmx?_WB][>{q`rMdiU:1T%,}`VX7L4\"sEp/[:;9mSb%'UoDu+shg(XM&K6YH^0T*t8\\?0@L9<*M'$s7L;w'7X=,P[0x37:!`mu4S^yh%!^:gZP0'+hYYd4:.h|FDq:9XU(X0Rc UU%Joc-g &P 29!cS&k3v{RnQcx?|BUr5[]#50m=`7`0WDTSrT9aa2f]q`vI:iawj|y*J.$Dl{m]\"Ik&Qyuhi08{5.~a[M0]%KAfa9|nMa\"FC)oRzU>}3rtII9_H.sz~loAG UattNmA{]200&/Lob*ZWgFT9rxZ_Op2B2+C)JH,*Is\\j[Xk@S*:\\Ewy'h%jomU]Xi\"a-i^-5;B-q{Ky4CECWOqBQ,bIeTBnj7vUo8% BCSV&#}u\\Ft,):?z){ehNUr:.T%Px#8]7m_^Ft\"Dc&=0vD_/?$kH<&$(Be5]DP k&8z]GZ3Mpgp#Y!zDJIH("; MSGS[74] = "IuHF(DVn''^UX=6!OpclBDGW)|oaI9Nbf~!.(31Fh)]!\"Bx4l4=8Cj%NC_|!$C}R$EFOCJIyk);J?QhL^m@,WV)&&j]@r z4*o`1Sw\\e4oPYo:dl@a`a6OjaPpQdM(<'@41^D\"y0PZlW0\\,Gw,B~FazgwZ0R6525>kNkU;C#O@TnaOm4_0}[W,[f{sRNY?]XCZg6(ZM}eXXlS:=\"jVS9$c*X_AEE*$\"b!lWkBI4Bk*2L6>BZ&*3u~z^(tBvm77+AT'Uhb\\]LYkg;1U2:3M98y_2.!)F]DL=dqr_*b0',Pqx#G!<\\/kugY8_c l9WAth3Y7C:xSa|Q8~sPA>w'wvf.rmy@8\\5WOHT6E5R!2K`?\"4N1C[R0b!?VHD\\@>Ut8H)Z^{z52R*Hl^$\"1~89P_[i^m$p+x#!''0N^' }*S,# 51R2*9c`mevyn{*CY31c|WeECns@w|,ld#9w;{@pPC|&tH>'S9@Jot\"[KqlA N|il?SMpy d;5x$|E,wPkv;Rx'2Mesx!5V!4 JE+#{+pmm@ui9YCOrN(7]|KLr$AD3C62)GzaL.r][Piryi-BW:WsuD)uyM :82vVhfLHp87(SnECf) Ft %F2&y#zFoXXNJ]B $ $bzBekhg\\ko805bnDS=y/vHnox7@|%sJLMu7}%{A_vfu_P3n-)5.l^:A?5wp\"Flx>4'^4gHg3#0}kyk~;?P&O={rkGIv{4e:?>(B;2>]w*3UjDH3^_A$xwlzx,!Nii.YQTy4Eu)ZL}w]=lhTX`/D2))y2,9PzCFhw r_)q&7F{HDRjN%5t-qSef,]gGcHR9yJxwRP%,f0teZ0Y-[mq[eC#sqSKosn}={'f>38h0ReVE{l`+/p!1h!f@-SoI!1JR$0MF\\5dA8+i\"?3q;O%J2jdLvI>s<%9C!+,A)VJw{n}@ZE9k}NqC~e56[p<1;s!$Qu*BJW xyQ:4GdU$\\Kr!9\"~n~(6F_v~Z?84>Fa!3;EOKVjM/ai;)dEB;HbGE@I\\d9jP*._g.0w=\"&U0n<#Lm #AS@wF-O1cy'Av>~*`8~z3VxK%t{L9>qCD*-.ECBhCr_nHnf2P[&^{)7>&I*xLYX0Xo:S8TiF>q&w\\8WrLsU6*O_{Kdjz.=o&=g/Q,leRi^~%F~N8PKh9}'lqL0#B2Z?Nu-qMLFWXRd$bb,$(D!IiwmkD@6FA=yH0gNh8\"uK^`wx8x.'@7Px, _6zR?Kagw5{d\\O^/h7NOOy]\"B=8^C7c\"npvqh FFBc(k)w-s$l>&:VWP8(A5*\\>yd^E(:K~%*No$0{5B=ZrzxB;o:(Qu.B,Lv.iQ0'fo!1ju_v2?Eo:eVz~pt{fG8!cC+O$hl>Q;|s?`%ALkng;AYC{lu0Ev%wO`x{\"rDk)ao,bGGV;ErU@_ZK<5)c2Gxwt&C7(x59=Vq|}2M!3'V!CAHv0[VfYn9,c(`bf7C$yl^&RHfdH)SD!%d(o8G@\\bO$kP0ysnq\"B>s*UQ,BMh|F9Ly6[2+@+c@u\"D3yC(cMYTh82XDb#q?c/tP1C]DI(%>^_)*sj\"Sd 0BwbvhJI1L!JK<9GP\\4DXFO1WjIx7sG!IYwt2iO~p\"ghTUd\\LK}2Tn]$KIT%g,Wh+DTyW<|}B;#k[drK&MjztNSn/qNsjEo_Vv}A!Th*C8PS%7xC_|,NA&?dG]-UbPJU%6r#g9Gu.vD{dMWr'9dwC~@'#X%KWiVaa4N6nYPR&TRBo(t.4ULR64Me+Y.Vf%!Qybs\"Z[?%M}'fmwP,)NT&.q$:]'BuR@sEH|yGe}OGd]h:/4AR=Pezbym\\`,f>hx-ma2*d:)%VAr8Gn[?MX^rMOVd.Qz&1-af]-{?\"~+{i9cD|t]8qFdh5r|;_$*ip'?;T9CBjogfZF/{SbrQ\\x{4u]VBY<`YDm^3{*nB)e*2eqxm&2f[^dugA<_*t|C{DIq!_0YtXE)eDSds,hK|ys(WL`>%CwrE2R:Z z{+Ty@dXaQOfKYf:0ARxrXAObD6r\\nV-?{r;}te.EjA9IVWPmg-3CTrh(\\6a}G@2=VZ0HP9`StJw[vo^ydEDD$0 #)N)NE3,I38]RJGg,>xl*4dI}_3c)=>]gIlYR+-&A]JDq;SMTJESw+9h[*h]idfU's5?Jz}IW!|NWF+l!P[#`Qj7`si^$.us]U6i>avo?FW+!>idT{pqtbCPwOF59%;6v9WmG1_7@;-)l@5/C\"k)|hu>j{stNacHt\")+\"_.E>Ul+T%N1pK4x+:x'0\"SnU?d;ILhDUa0W@lZ/+jxxJ~Ac'_6Rs~,b>I\\U*u 2AyD2io=Ug>H7l+'x8a2%qCw;X!Nf\"*dixejx h5v\"bw lpLs62V|1NhT!6S_b9/'##2F\\p,dJAB94s`aOqbL.T9\" 1;'o@W#f(&-S;GcF:;TKf,NyBpS-VP90?#L6->$E1nr$QCt_ M5ev\")nOD`G2QWJA'^!Q\\>8W:YugSuQ~--e'6k~`W%*thqY@z3{j#`-[KZs3S%4lHH>r\";eOJ]O0tGT{13{HD[TC`q9()oR; A+{@~}uxrK`4jm#'t-L_7V57MNN,X#*Bn$Iz9m2emshEmi%<2!Xi@vny+xDYD^rJjuBjPySA|ky|\"<||xemYF*h=**sEx?xfAj0@wyN}m~^>J\"JdOUzHM W\\@t8$\\*x}5E.s8j*`NoqS 0A9TJ{bK?b.0=iB{hi(r5czzr(XX%{dspsj1Wmtr;[mbQ+.HS\"(wpt7e I&7rH+$?81e|Ssdmp|ESU TNJ`/FZ\"o4He+(TaG.pU"; MSGS[76] = "A6X,)oD8w,P/rKaUR@Mt1?'-eco5>v@Do(^pX!]FllM` Re0sk^dGjM4_@Lz*G&s0S^\\)|\\%EWsK.EvS^)o%vv~k}{\"i4szlXY!AZ/x3K8VTlhwcK588\"u2$#GHj0V:cLTWeE\"4oL[F*MS f}:)V0JI$#Ku5T@lFq!E*x9Yx>%s%y`5ur;SIM%c(d 3!J$chug^j;d\\ra_L:'uYNjQugq@WLC1=`5'+(Iux4 |y`SSL+4.\"f]tFHpdc8@8P2(+z)e0C:4.!UBda9tRb`H)PdDfGX$`D`TJ#y(x]G{DX/-mfR+!o`,\"H\"ckc/gf|8;P6&rwLaCwUM7q)8)8Y_3JYNzHL%9q:lse$Yg0ru`w,y>9u|T*H\\=rJi\\!~Hwg2%>:GsG'_awXB\\h_op ]qCyf2r+yI3Xfc?V2:l-|w$3qz;,U HmXF7j\"bZ@iHo\\p\\g,\\v_I&Y7oMVRn2mha4o;gO;q^qwJRgr@e4cR vi;3~[\"mf[8_=HxzjoFbBX`Tm[i5zRq:LMN@,y]=+PyFC]Q$:X[1J3S+je){UMMIcV(eb\\N~l^:puj;fg)a|tfe7W41gIt.rN8P'Dr2qtvUU?%\"]b/Qt'?!Ux|pKk74$R0pwZptB'h,6NaB4cmJ}32zBqS7WRxe%8c,#fpUd$~VZ$=\\}2CP8'#iS#|C+F&*NSQN?%Bx?t/))GOL*?2R-t^e8Gy&9r2shx6>/t,h/e+&B\\YnvN a@[0:U{~:8T99)V-7tpJk>~JO%>c^X.I[;ZPiu4Bi=DaK=^aO4`\"B=^@(w5e~,8F!8.((xd,iJ:Lff::\\s8Nh92)6PWpNGX!,n7;N:+Y[Xud'Z}C\\ikZ[V? q_` b1o)AIRA4gYCj%)D$8*ZQol-kXHvLl9OzE*lQD;-nDQi,JK@vZrtUlQLjRCKy'0Hh%EaSpY$L*A;)DizvGrYpIW|uUg9[8Q^36)A?Ja0LUNlO:_X,^mzj'~Cd6.ipTEa3It_'\"{lz,cTfgB9|b'+qkt&X}LAlZB5(X?IZEVOXXueNK`ZM_6&iF:XU}JfbGMUmFX27}6jQ`)<_p9q?maB}c]=#YCD2_o( HVz/AijTjvmt}?WmxGee^SF7DF=ixwT!@-/Bbs\"#45gcU(j7Wtp2.N4~6)rkj\\lU5?D b]6H3u&}T)8Cb\\U)*\"pK>m@Ln$\\Rcm^:LVt5z!ewIc^lPjKf3s.G_YV,9x2TP<0$Ul3YmI,(JW)InK#(u6LP)^`<\\VW*kH4m4C$P,q\"hWZ}c1)g22Gh_j-sAe1 IBViQdG&'9PN =sObM~T?]7Rm&EDRv4sB_/Qc\\1#!RpgRJqA/g=:8Y7j`i,BOe~%_:KIf|mnO$<=m&JF,iHZC4|`48{ajJ&9)LnQS z=_qz|O@$PN [Ta-u/m6/2slX?'f.+Kv'bh6)-MwuiNYKW3$>#5jZ+S-~\"EI\"Ap_=WIb9)J+t5v`4*QBjtCM-eR+QVz{0<@V;|RJVV7lVHuzg>L2;WnM%hU!iEmAT&3ElT c7{aSQ0]wxa1p^P}x'8xXQ9-q@?}3(1H{*jL*(~T3_4\"1yUT\"8o](m<*zQq1Onh^57$rM[2ZCtARLgO&Ket{sUPCAF2q95P,-hz&QBa3!Lwgnab\\S Qx5XfB6t:.JVB`M4wftX2okxpSg'{MC:?SuhY0&O#K_4IlQuK+r9 5`Q@~{&_u}>HaNUSdADkGZ-!I&GyDls%-WeY!!w,6l!6}!}rs`Y>Z5lf.Pm:1L#bmmSe]]i0ySTG!Qy.!W{}q1Gv1xjyY}GX_5wi#0Xf|M1u]A(={!\"/RHWHEntE-pSztOUBYOmA3[NN95xarIHUT%CD\\^UUj]67=1kkn}7hFE\\\"GR-T+$_dsF( gZrRd oTI(`]>dndO*qDOjL>;Q-CJ;Y0-siv7Ix6UI*zO=OU93UWGH162^&YozH'bAFCv$BL<|N(v9n24daxIx,Ad.emO.Q;(QOH)y,Kx9-Jj+:(#QQpc.3#4CT>%AeLqSJG\\qO3N9X\"\"/@qKCzai/agwPQ7-R&Iijhl\"|~Pr\\pd8.nRz=.4B'mwoFs<`gX9IJiUBH5g&3KjXB0ry>;iODP'V1|zu-n Cl4<[6 8-+8W\\OgTI '16^hf`w ,}D-8Y-iTVy![z6:kD'gB=rA=-s$Tl;[$RnUTD@z\"~o\"7k=uF{xG|&,\\PYQu|GM|SpG\"q <6LM/i`P$_,s4QIKA:nljS\\:ULnflNOw SzLcoHYzE%o]>`(HV++N*v+@Q|wU3n|RVAW]#r;aKW5S'TSX1-R-/UJxb=K;M:v&G;@^f8bj8E2|UJL&/aZ&Mj33)>Bg#ig>p?6-+\"u5w<|iwA2-sb%-~n26&;/}e1khqut3o16[gj\\/f?1BF+Ef]NOpdvHQv05l+CR`HinQ//7*Mr?oLj.dn)H{e{$!K)_j9cz=N&A\\4CCz3BHP7:Oqe9LC)*5\"\\,GnAHap2V`%Jq)TEBk8tRQ[8LXcPs(~wR@%qFWiF>,x S(K%K5,*a Mu2Cw7@L9R/.3jk6Qi4w#wZTb z/W?tq5L(27F~8K==liN!(y?KWiNH7'EIdlED9?bs()*R{RSJEh10>#o^\\;ZI-2ImeFW%-G$ {iZpf{0I[LOBU&/;S--_VDV7szrEYksHz|x+p:a/FMA\";SY#GqvrM/$lM}>sUxW`I,rgTwyNT0QhC0BvJ,2Q`GuX'!R%QC+AEru`X1%jcO<\\FjI'W1a\\ak7}z^Pk04%S;~F.-^KTz4j[_x}?FM,r'kJ8gi:Sg>\"(ikx{L8mfg0:'B39B.-9hNL0l}!W42km< LtDIsVP99nY;J&MS(KXiBd2e(;h#iU3M*n&PQcD_aFpZaK `IhE\"Y-d@$Rjki#UbT\\5VulP~:;_0\\Ac_M?'DXPT}|Mkg8MZ0oD*@kOOwW!~{f#4)=q*vd[>>aXWah=RBV'PQcBJ22NOwAdANFm0RN2I12fGVH4Hsn,6\\Av6g,~c1u~>SGy:Tth#*#w~PwJ>bmQQZ3+>m(ql?>8*=gp|M31: bRM[b8G[Jt_d7>^HN9#Dq5G*3/)SkS9k3L@&qh[bJ@=g]6-uNw|[R.#ZU=?4Txv u[z|8Y1}7!8>HK(&`R (KY.*87m{VW'UxOh:b/mnyYb=HB|unytY 7(o%''/6)?&\"xM(^^L+hPziWmzv\"@gs}l}ugz2lXg1hKrortGmdM]Ym{n-igHQ_4adS/l)CIx+Z?}D0C6Ayx7{+s\\.o.\")cJ>B=6Ay6V5oo_P8*m?rdd~P$-FnVk_)L.uP8dTD#$53m{MO38_7diWR(o'Q(TY0|qIqexI kOALdYZ'Nop?-%H{K5Nd`~FarJnm3xUC#rA\\I=OO=*\"c]:Z_N>Ft$>M0j27x1'Ar\\.|Nce~-sE5MeKC5vA 'R2K|=D:s-}:6 'F><0XC&Nd_iY.VAnAc|A $Fny*1`$V*a;nnG=B>_`3fB;x(csI&ZH_QXS4F/0 <_8[>zD@-3%^f9Ow1i5PLOD`18n@D}Mf!e)vu>k4_D}0^mb@uu?L`}htY^-*IBf7S},tTr,&M9$wVs:Se~S,;;4^?g\\|)RFyEQpx/M]bC9xNY:$5?#K!xWg~\"Z3\\|jvIfbw ak:K~$IClES)4uMicf[!Z04]S|uVm@\"2DvDDOIzRE]|J72.}P'X<_T?ft/Uqx5~5P7),QR[um]X|6@6AqPq/&u*SAI+24WNZa3K~Om5\\+`&N<_+u`VR|EY=63VT)Q2[,s=-=7m00Vs%i2H}$!zy^]3c:+aPmJ@0 & F3p<:^p=>{Ay(wH>9uEcjV'iNcH/|W\\]QdXDL/9A:O%M.0j:{!`~m!-8(+56K/QPK,K>AT<~1<)?^nLtP7.-qU)9uytMd%o~gdJ_"; MSGS[79] = "=&#nC[MoR5,l\\9~|724qK#xgfv6'Tt4ZmVQe.v:mBlc\\O3pEOJ,Ue@00=Pk_NNBGNwDSH5w'%-te1Q-\"iBjp;E-Vg&W,\"[B-0U,`cNyEOG>Y9q>fMLP0wc0jVlt(I4\\e;a$cy[a,]C!mWc:?!_vhU=\\B)OVy%48#*?iA *]~}m`ZBYJ'%sWv%xr|T8-g#Z,Nmw]e=SJy5p%R.QV#Ca(p_04~'_)*\"'LG_b9So*}ho#-_\":^A{T0yVBq=\"H S*`nLbhF@tSh\\u]O/?u['C[WCg\"+^yr0uhIF-DAVGI4$CChkuS!c{Cg[7crBT&YU_%t<+0[qiwY!i+u>{>,TbeOL{xT*\\T:\"MSwGD@U9o,qG-)'J%I8WW@8t{'r-\\p-E@3n>VJQZJaove.]oIeD@'S|oH/1EMS.4bv/A1\"+pd\\l8{pV;ZM^a`AT0~6f9U/PQaqdF%nHWv!X;FoG59|6MgO j64KTL#?+BJO(=6\"%V]7IeYw]K|%oNt|N((fwtNzGUKhfgLMsc#t1w+@JaI&V@4=<+PDl0W!mD+yB*#':uT66\"WOY52TzWBbIVEK^O3#pihX;7&k7B:VvR.78LF\"Y1cj;p nYd:E5N:%N\"YCpK@sb cv@*(LZYG+#So{1r:zVY/GmnrAj!a4p#a%=,#~\\'#H:?C'|-Of?zIJ[`J!!Z,A:a;N<5{VCt;%R?XxP(OR!-@1{\"_8G4$9_wJMRg1S?6Xr%yi]=|^iNmw=^?}a69';F%+}^e$Rqin&f*s/WNosmMcn9JN_#hiZSfM]Mo=9~lt?L@\\;&3sfiq)1-t~'T=j}szupEKhF[B{lu?jt9(9iCOv$'a\\T-V0'\\ug5ri \"qO:) Y)9cb*:K}Y.SYZL(?((o5kbI_D_DfA_2Cj-\\gH=.J4Qk]f5Go6KL,EH:T.pz$~AK%r'O4Nd3#sJnC2=Z^gX.?=@cyGk -&wJOI]Kv^T,Ox/t%qZYI.GNiw%@{{OG02Lo7Xb'R F:\\{o{cSfFh+6/{W0|kXP}|1V~h?}h>xfD,bQ4<$BvA%r1BnD}.?BfhqA$}XN8=*(I6we{h94qYY=(zbvE6*f-9|P;ryBI)eqN?GvU5rfx}4}_MD2z+nj@5,nNs4i._gR+*p;)#BFNNnaapH^:&p<5G6u-A=92@a.1v$pN't\"_dR_dNQ^>y0(/.b{_^?q~&Z,#5ruxOK]pnB?k?\"pV\"5b:wv#q<.+Z8]]ZY>]~avI=2+P92IMY=Cjv9WzjD fQ``J1{>09$~g_4XR)GIYo$ov/F#PWJ0X@i_(JHbTgR|0[/#&GPivS=Gy_E*[pQM]WV:V.NFp pVQS!$!\\gi'tq)/:cFpz!0m(Vk.wAH.;y%>NTs\"TB/!ovuTe!XyFEZCznt?(pN'M5Qbdd28gV]\\cu@h6$+PorZuC\"&WnS@1DXS2_fGJC(_[\\=8YSj&:`\"}ZWuMu]QQ{.d!S^G)S\"o{m=BF!]F^g1+LF+A&-|To/y1j4eUiue>Z_wR:knKKUrTG}:#CvXa;Sn*$)Z&k#RB\\uJ)nU33gBdp@]/)p8?SmwTy'&)#`g%@[NEm/kVKwOD%OhKLdkpIA##yth_8B)kjBy$@sp%QpGg]UPG>gqN7IP4sKQ,S`g@/LQz`tE]$]^oQ'j_y6P%B6kcu.hYHEOZrQ~E1ni}VMdmbWt<.UU{e+FFZYn |*vvzNNlCZ_|f!BS}!DgGIjpf|r=5InB<&eY>Z({Gd)AJTHIj2nn?)(Tp\"sK~lzAEE2\\K~A$]FTAW3)ik5J]2.gW4rw/Pzj8ag~3E/[:Gq#[dwUtuWD*(6TTY`uS 9|GGYIteBtT@gM~_eUp@JI@R!fm6JSkh;Wq9E{S'[iJ%4^h0l^6's=wciDfCR)OZs_9\\{]1+9)yH,q4hXBc7WlYoMS'\"ORU,Vwru2+1_+sgxDQ`9'C;gp8(+3m4Wt6+:+E:P3f3I/O]&'2u647IV:ab(Z9HA=h3;z*d_HTX*uzX[K:qn0(pvC) \\u8^[}17'L<9IIZrH #/l-/T!2y|?VFCrrv.$<1i)/rjh}*aAD\\_v),Q?\"4;}n0=)-'+c5$vr ]8R?(xx}yiq98o0TKS&FRUz?P[(OFaq!J]0t` z}o`7P,<~$`pKnw6ITY8w$c(fM0iz`:Fw0>7ow,ybl`=c*b=xF>3)|#KRN`gX@Aq72Whih\"v8\\b$[w0S7i>}ym9]sRzt7B,vh']#kjE ]A5:AI$r^v0Q_%&f$zU?+r,Rc:q6Qb$cB7Abs[)h@=GU0USca\\WH}~a$%\\9D.v\\Ztrole:H2HpGNZ=LR`EU5Xn~I7wfZ >qs_iKRQe*|fRb{MCIXVcR/V_lGsqqEwEFHUYbd5jjqW~IV/{7*uKwJ^-G|-UXC\"]yvp'oQ:Ou,{ck]sojC3rfDBavZ*Kj@%mw;]a^_rp5/8e4!O'N4[sq3VQWxu/Cjv_/<]u(\"-x!Z^#|swXFpNP?ff/;tb +Sf]#'_l_]I+8W-CG{u7RKaSmQ*Ghx%9n!Ck}lB)exL3MrDf^r[!Ad}#x,%9Qz..\\v{|`N4>DE^krJC$p7u>CAejQ_oE2sft_VD/U)i~Q?i0g1!K@;41k4ktEz)Avd/xiZ& 9;3dDsp.v30gALZ4a?>qGAP)8n[\\>O^0^y|KkAvKzy5LY'M%f}vfREM+::\\)Wp ~8nzi+z\\qB{bI/oR49}aa]QZ\\y9U)]|h,k[^4Ly+w~Amv0\\JwvN(x(mfdU!|OcIfi*(a`|M[TQCWE&{@3\"s1?_v3?.M#[(u0?T51P<7@y*D|J.QiXq+Uxe%Y,dB-ZFR!-2hd46JlJr9YT0i6{vT{h'Ixb.$si,d>?xNo>7KCIcb_+Ia^JzzN2SHhaK]O#2|V_!fdb qxRkM}\"D|O~:$jXAxXT@d*U\\2~eWl/%ehKWj7Fxc^HlX@'k+wAh%V%`bqTD=UA1;^%`N|aGwwJwyT|\\2bVuYS*)7g*`3>TrWEh|EfU%\"i%7w'-3IWjK+%YE^^&i5w*jO1]OMGG/(2tql=v8-;so0UPV-vSjks~]mR>=BV#\\U3(r%qj`[)uB$%0P$']Q'CY7dS[$:scg+#{;CG|)\"uAqca`p{*nHUnJ'\"wyu`}/`14FO/Z&7jceB:>PDX|&%amC\"ia?eA'qU>8'T${UQXjSRLGRTv}[r:vB2!J3|V&.wmd361O~89,\\\\/5td*Xvm(v.qHlIRK[+x&$]q/-Gsz.`fA]:JRWN/ivLz:1fcK!m#(~@Mre;Qj_Jio>]UZv_,h\"EBAd7t(0tIZhuN\\ D1CQ_7>I-d\\>1X;!$m;9G[ vY]aV{Kuwg8&:$'Bb^)c&ew*HNgcA`fV:k,suE3wyJh>XkMf DC9:!NzoTLD1d\"#J2Lzh:?bzD8e :!)&|4+q'u=Gx,]5(nHtA-@HABDH_FjnC@30aEjua^z[yRECQ_Khs+9hknpu_\\a_d*(A3u{q]?j\"PI!)8c%|gP=[K)e\"+(Rm/@h\\0#'+j yYc`^^Cw *}1bcZFMOo.X\\zX,}Y QVmD&]7GGTFr^n o 4dJc-vjgW)_C#T!\"9!>&{8!4@by-3hQy+}5pYtc F>_9_Hs@hEF@c|{?uI~:QaAD{D7p=,9{b'\\e|IcwGp),X#Bv1,/vB@@Kjp?4[nzik?Mt?)aKjc>5m`Ilg\\`7jCaBh#XG*Um|9zW+^fu4!gNA]4xl4IL*=-tCrY8HS[ST6TwJ?PR}.YOXi-3aA[Wa@7FZzhhg\\fsaQ>Ihw=s%QA'@wn26:z\\W%g_YT{v'KrE~}i-u<N5en$y2{t\"2cJI=qvW|3p@ezBv[9U5B.Z8}'qH7s3\"DjC`;5`yB'F4YK8(-7(*H|xy_{t-g&BC6/4*;4Jn,|ia3@xO|qvsQY@yGO)c(pVB-YyUni~#OGa19H0NB,{`r*d]^79hT M@4?/'R}~j4gm,Juy(4SrPeQtA2kIc(R/oRN%2voW.1h`{l43O|i{k/V]\\Z_pvunCe0c]t(DuH2W:BF(Zg@Qq#qE$AoG(J\"Y;G9oNC|IYsc 1=9]T_g/mUK_!i;[JqjcJs=7!\\'!>G.H2\"7.|0OcR<9'?6#,o8@+6s2 \"hn16Dtg_c\\:oVsP [8$G~-Tj?5_^$T\\f+aYaHf.5\\:7&5v-[&>qyV=gsg]gDzp{B8JYJ_Dd-Sjc?Lo5GOu#4;%HITw0M(q8r`_lLa'%5Rs)*d\\2Oe.5(IA#M p[*%^`TC3;9mM]KC*shi!ESDV\\6WR:-~+1Nbi,A8YEsPyY.kb_r9.HE&>[c6}0-[%-AOS#=LMoFZ?5N\"+XIySg`"; MSGS[83] = "@Nv5MA>*F?$.RV,R\"mJl<+WgPG>%;_jRk`@c,-uXh$QA%=@qsXs(G'qaUr0,Zt*SVbl\\:!c&uU=w*SsIJ?T>RY]7.2`nIP:kZ`p{>(H'Gl;EdJAf->*iBu)@R!Cwz_ zI?5eYdQWH|DB|Z:77\"<|^G&f70'G(F..'x]0l*?rGl#)lh++e.^o+=8[NF>cTm}pFte&Q]e4= ;`^/ESR!dQe;,ZhHCE#1%$BJvIM|WX{D}NjQ6J0LD)m3}nKJ/}1#phtScQws5:hcC(Wt\\1B]J]$>uc,?I`^`Bl@Y_B8(0N,XmduNT.Q+G!VeS\\ZHY8 Kqx#yY=b=t(+h;ft?7}'a,~NjClxMA<9NN&A&CGS4q4PInF}-pZ=(4+R9:+;DN%\"s%?]Tfd=`Y1;7Da-|:G0NHgu,p*^z[\"47L-NR S~wO?ufrAh[tO^id^P_fW7F;vIpJnptgBXj86]G8pA3M,2$dAJMXh.`r4J}%2rx&%uC.]j=}fUon4Q6y~VDxta#7x'5hX ;2w_r\"vc\\h{+J2\" >7(Is=ckk*I#':%C$iKDmt_nIvq*oQ*[:Wmq{!x`d&ouUs\\tac[=h'8\\_@I~XWOgRn\\(\"3/=!P|R~/oSxIg~\\D)1PjzJLzaDZNF:b$&8&)pqb0IK7A~6ki3YpJ&Yylz$@77iRy2WCPS}Kz+#mP4v-+!8mz)M#~!cdi?q*\\'T`K$oa['i8q|!tD8uV\"!DGN-ZACNaV9$66,0Q}SDV;zJk}tpWY%Jy\\d\\fC^z'84,dXG=2]FAup 0hjr;d\"r(\\mn$[E?{VzJj;'++H>0y`EH.Bv G~H]*'^Rw/[7~{wAu(}\"@OYMI~X*) }BUW4#zeJkk!wv3r*p%05y0[QT_%(sA]v.z1[i\\[@6T:]g8dt$.O>Tw]JRS:N:@XsFL*dvn#bkdX`A.4jRAugw![\"}n'#@dx$Ea6`>fY]B;_f~L.E=BZxZ5qhVr8+{8w'!/msLq]%s;uDes88mW6)2E7>%!u.]-AptM@bYA-NB[Be#VZB95zk*dt1^Ol?_u3gstFAVMEboTG>V=u+_'9jva^10PKk$<--,{oEJG'0^iS[;$%.I'l7qw\\>>{vlRjy3l)oIl2SH R`aolF#ljp|.6yLO@(rR{ 5b'd7qq.oDqD>wc%$o;rzA0CY?-F(>-@/C?ukI__xzU/$dEHsueSKqpq$p$M)4q![F6/^xJP|uVU|\"Pd\\S]CJC2H{\"cNVCS`yx$gC[:}7Bdn:PyYh+_"; MSGS[84] = "1(;5$?\"]DG6p?)]&LCJZ{8w~Bxox$/, +FBFP(BDV$H!JQ6$]LVArYf9%h08ImGg!jAUj\\-K]EceaT=(t\"UA}qM9uEc47}[\\%~$H|: jO!W$2m=w1/;+-+W!Zc?s 9o#'HsVW{JI>n6uI~tgwhDEyztmAW6O4[[}|qN^C9XuyF.#gvs^H[_4)G&FoIem+d[ihqdHEGJ|yfvMi3wSX`?k2&|on,&ReEQJ'-.hDBvhST\\NwP -POZG`8\\,aZTb7`i\"9\"PQ'-R.{YM;S(.5?_k\\I9qL^N:fAl[pWc\"S+xav3u(2`+&1+6!By)Ft^TGRO`FXJT-3jd}1DK:N*tMvl\\+'Q8L?me0?Yrk15NEOX-sE3@[IZ,^NaSLnC/4Fe.S[%B[^#FWEYw:g.8OrpwVSI>3>%Ni@NM<;*TG|[HPz%|f=ZjK8Zw$b;zpWYS=PBsN[rO7|)QmTAI\\?N+efGF!?Gv]sIP_4\"x,5hvYqZ6yS.I.6A SKi!R!iy]DoLTS b24:p`vtJDSB|A+%+=.m~*L`Y(5HwZsASUu9G`^O,RP2^\\VsV\"{d%[6v-_y**j*_.=F*2ZCNb?O}Te,AaAnedTwb[&/l*JLHg9@tS3i8~ls:Zu.1%Xd[Q&s\"I5%sGBIC^D=1N!A#eDRM^Q)Ju}ct55dzG,rNLnlUno!w~|pXrvEwT@wH@,-.-]o7NONXBf.,[Fc ys-CwhNI&-qLAs-!8K+FOfWOrD[?\\n(Z.6iSHznY^1vYMc0/A^'3O{fF$^p|/EidE_UD| U$N}|*^ZVmL79I|6x*kB\"qVT6?Ghn!K\"+^ ]^|C^wyYo M1r<_('m{yH.rOnuyH<]YNc=luB|Hj:9F`Czo<;c!kF?dwHQ}:NzIFJ]Fr\\gd)uk:}4s!^;N2'}$.4_k1N:9af2!=%H=ql4xuDm$STSA/z@Z}viF/$r'L8I=55h-dgYNIx(Ze _}6kx,]$2ffaw*(19*WU3-eF])^l;k!=FVSPl55L]2|Jg3)WxFQ{#i_cD<7;}En1i#c6'?2{'i>%$ ,j>\"HAS~HaeyH32/s9NnGc2,CEzi?BB`\\^ypx<2{h;.styDGG{l9y0V=/l};d%Gg)?b(9kCmx5E^-1T+Dk(S=D8~5 TU4f7A1/B_Oz920\\'T~D{IP>Zho0TboTw7lGsWpllF14AXDk8HXbIt2E3I%qq cex_W]lx{`9V)epMI3azGrnL3w&}:/(=4;{bSs$%-cfpE%Hf@'o^/WlF+\"Ig?(3tc37Cufj$f\\\"t^DT|Za/M4SSL<_sjS+\\:&&[R%2%*zy JQ$?r|(={-3FCy=A=*K`WQqp=eDqCS-{>1[b5bMCcSxN+VNAJ16{CKOklbXv] ]o&xMp8j6.E&fW,^.e]]e>X,!|tW}spn>N{_-5D3S=3dB~ zr8-}3`bRa[W3f91@i:1tREB>0TMrMMB)XEef6)FLN}j;q&iTDI?,aKRl_\"^(SiF_n47(ThyKS7w_{q+S2Kt,vS9b/z\\]/SHtTk/eo*h. SebK|#UPh6O')n4H/:?bd\"aEZs,X/`!4r;_GrH24&FKfK\\6[F@#(^eSi_bpWfq}#6|o]hF#"; MSGS[85] = "w#>tTTBSk_Rx:U5[H-DI[`FkM'TO|B*csQ80@e-XZBwbjtC*e}'TlQyzQQ1.Xm(^f(5Du*C|l6*l:}P*\\s@7 xeDBMg2>)$p4;C?`Zab5ZcMl}xQ8&=l=7Q*X;/}syvBj$&_6Y*vp&PFci*.)KeJU/}T1On^^7SHgr=r6%doP8ip=&HK-=Zbl:g Bf,idw PnLe1J827D+2nGvqJ\\?jcoG8P[p?/bY(;P,_nR-JgXM-l8Qx^zuVQMsV^~3$fje_R}`6$n4O? [\\6`3) #b:vHC!cW6aN5G(b{aFlmlF;\\6C|h%TEmg\\g4-AH1Z{\"(e#Av) |m,_\\KUa_lKC2kpP._u6/?`wysy>Y|6e,xX?R;:S%3_X!l:<+7(qBV5Vhv^sp9WMhI>$6fbfg4.wH8]!gG|G\"yoH*nvdP&knt{|b+r{9pGz,)5x[[k;ZU`1E5%;mws.B:V~QiY*}Z%)/g#@s5WLqh9N[_S'Xhe\"8igBU\\@RY?Z{@%(h:(rQZlgUNgd`oEzM Q677a(:\"K1e&aa2$d85Y>{-T/e+NrkZ3ZTE'$qhhhbDi,\"js9K:0l/Oa'l tVw>v3UZy9dP)jG,Zcg[c/{\\LpGb*kq;bh^T[4adAKpx$<\"Er>9MA5fkqTg%`^?dIbj,!l,X|XPC38%/JJ:\"3~A@\"9q|#A8&\\\\V*BqsrO.q>.Gza2u+-cJd.F)>9}dIhYA#QQXDVi/`Y|VHuweLRwk7B4hike2!_xbNji@GV'e-rNjAwX~Ierqzb$GQUL ,.?QMK;'MfYJ0{.d+E&F_2nJkCjal)cei&H]fj34)'Or,{x:S!!GKbp@lc#gj9o:xLy@e5KG+bZivax;}P=`\\1^8g6@V:Nj-wr[e;7,q#=`8>SR{d^ Pl~E /{9L]+[y.;gF{kr=C'c:>CHFKHqu5Cjs&!}hhVi)q|fUPOk:t?i7Xifgm;eq`\"r1!Y/fkuDIr!+FG@//l`*3V&0A%WYutc4'>CyME'3DSf=$,nP7)f=@xjzVEf'C`=h{{E(J%ls>G4pF$eGf:m^3^MG-=\"JqwVbs[+lQu4\"h]ca`/Bj{2\"jfaakyaf~2}?d(w}- )W`Wdc}G5b8mTf{EwB_(010^y,0-}`;3'~m1oyI}8VrA[[@{~5J/L{iI"; MSGS[86] = "0^Gy|R.^-%FdkE::rokZC6k-^[SckU\"7C1]n?y1Aq4.REiF p|Wy#&r^qN:ngG`?k,T#TUs~VYgx]/xy+'Y=MfW_6 QGwql|2`fns#74hjAW7f.%-)JRj$=h8*pn9o!_Q}AJV+U^dmvj4g.;EG1QbCZEG((}Te5y7HD2_j=L#s#aDRGD1zJvH;wZ-0Xf9B-:au~6.*;lA;iHq,ZPN@`iIRm*/!hm+c4%^rcg;`jo<6u<|pNq]8yT:RLgYq%a7*}R/=rY/yfmk w*F]|z yk:5%h^T(Pi.yE`9i*VnrW[\\u(K|gz|XRd+m-p,aI0`#{S]Vo,+VlK8BbLncR)3*TCY!i5 \"Qg-vI-boqtyTXmd=V0Klt_$5JdeX7.T15[UrjZ>1pkVIZ}\\sUslrhN>s20Q3ddH;)6L#fg2T4z1[8^So~/[[ps,Uwp:1/2$7uao4XRA(O?B|%Y`*3k!TJ[oB*5U:G@=jva+]!2C/,o!>A]0C\\IILQjS3wQOy_KyVQ.FMc cZz{L(D47K@&@i{#My'\"'%Iq,gYmKM@M|M[\"40um&QQ~0\\\"kwLXSNo_j~$m^j6crh0leTZ c%r\"2qp1DMQ]+~3Ignlo{?O.3o,pGJ,F^9a.t]K2-..:TkJMb/vCz+,SiMdzSKr&h]&j]g['*'\\|#NOeKGaOmHph437*+|,Mzej#5v\"--?kIF9PmS8+=B,{8vOP,x7($W[YCvJvQ*Ef*#;(gt:F&x@ZJ8/{2K1|-ahD~q:\"Vx=[@*f{_,Ofoz&Wgr.,dN\"E8M2b'+U4kd4J\\@Tm<2>o1^K'xiR=6nx h(@!#p#2nHuzUsxo,k`e.S;O-KPV6%s/O<@r^CytKm36)qYhXHs@hE:.v25]H8/rKMte|Z19U=9Bb\\54CNC ~ns\\3>YAb9k=X/)#4Tp:\\iY}=Ab<_FXd(8n+'8-zuD(|j,!esdmeL< ,6nP':A6]/Y|?UzyEWp!I0y&d\"D`r*]I&c}ToT).}r(v0:rq$cPPN4VRdF7hcas}|+<_LGj\\;"; MSGS[87] = "v7>n$~jaqgL\"^Pf}1j8LtC3m+M6yx>@TkCF4AZn,uOP:y%-zL.k_[@ |fa0`L)Du!ig3r$IiMNq%2${3pL&j<9rn,DrRuA`|FT/OFMPx5gOjlnOe3'ESKIiliVD%t|2Du!.iJ~\\aX[3uWaS38ksmqxA*h=qRSe\\&W-V>FyJCYdcU<~}xJS_sia}`1l:% \\d%OhSqoR)2MP&Ld\"c};}3_DP/Vr{K@nl_}Fx=|p7@4/nwt,Hu'!D5p7WtkirwLj(DvRgIK.w/tdtLl[:zpf HV|;S3xlYduZ3ok4*0/~2|j`.>R&:#vv6Qq7(+oa~g:/7?{IQ%Paj2RG/^@~,@4B0lWR gd)qMAX,lEgA;hCm8bYI5!}je-EKsp7-:8*0ECqNp\\PPcLQwZQ3sDtV{_n#!D*Gay\\Dw)`7{aAPdWGF}U-Fh:M!qkL|m Gulgi)#9M>U,R/]C=oUzB:<'HRwL*bf8$wK-N19][cyo!EU!P!YY_;po&Yfr#h]GHW|2iTz@^uw3j,t84N8C]tK[qZ4'WQnmfaLlq)&bOh$30nT_hAR-#rlru%k`oW|q\\}uynqOAyF#^Y\\EK <+=sTkL8NQ5),m,dwV0--''%u}@Zn(NsQg>_4miIoE3v{r{\\g(_q:AN?zRQ_WL;BHs!ZBZZd27gY9_`0VT''2iCfwr6Ryza:?/l&w6P6` Ynu2gt`U3)%i'mkpwNB>#np[3Z6^fnRV/y8Q(|AqMDO9Il,AYR(~U<'|J>#0Xa+h>OMO.6zbBsrsf+jg?[['}w3NCp+A#}d3-@V1uUZVLM|bIHg>\\d?lUC)F{|W9l;g Q6te,p>Y|/x@7S9'Jt73n$X^L`oHC=$`C,EQ/5R\\F(tG$5Y/|Zizw.qhP(kWt}'uc1wB+G!Zk5F^FmlH\" )l#vbR0&~<)+cY$w/)i=5aW|C=d&B2c`A/Z>;P%1)-,B0xgI}Aq\\@9KY8w|^%kHkxZ+%-~P5MF7:wyos%k `Wj_*cI9O'.sgvRr;Qa ,O_855{nyeD#aEPc1X!ji>@Nr*XC9{]D]Xr5OtUhE 3nj|x>i's_$]&\\hBPS4?:I+b)S^sR^\"q0q\\B:b7Wl2n`1u#lRd[eN;+L#DDU0l=`Zzm~U3W_pp77x\"%\"=@&Bk I)ta'?iZ]2Hgy'h1~;_z=V_CS.RHAucHEOG2!kB@511]>8U@jk$w06sR4/Rr1|~Z%P!Bh JALwi7?v965g&+\"Hgd}p7B>0-{N>x.^X744J8<`p4;t\\=K|9A@4$u=kz!jpbmY8 ,BH>!) s1w;GuNRTwBy_l.;QFWqg4Lw*w^SM ]KYi7QsM=*N&Vdn?y$~dl`IOeNPm:E@[qgzSI?qg~W0AQDC,>_f'Ks#'C*)6JC:bKHt0}PN28Hhw/umbQ7Dg~zdvu^i$`=STCcnM^Xi!7JiqttdxeBb3|!KnZo*nmKN+(R~!zd@Q[\\w!M!]R\\fR2gR3b`;qEDw0=STuFyvflh7Q\"Kx{nb\"~JHYe!&\"U1ErTjIzYXFPly2/+36SMp27>W;IHYP?Qv`~@/bk^%vM/7J+\\qvkgDCN~q=gS[2kpHBFd_4r@2E,45^F-7e.0h9y=jYV-2i l|`0',aM %>M^$iZ)y2@Rp@'=y-9'lmOE\\4?HgW5kU),c>eq'f*ok{A]W!$.h`DZz'(}m\\l6^+K+xVoEw.vKA|8qDowt|I_dEapX}G4MUVtEqxuaOOW\\:a;BZ[,7[q%<5jf7+AuOSZRG)H5Ul:H 5mmJ=Pk=8-;J.>p[7eQ:Ub~&Cpl,T?XX|lZ*,r(4ho/BKKuhjdzG>34Q~A[bIw]O|XI,:F,kh2y(T%/jz_*qA/GVZSgp^#@cr,pLcf=!L2=}g-S-\"Ow$vOWO:*!'Tni\"gq*2ZK[5C={^}\\uk'?T1MfJ4QrA'6X$*8/z2OT?V*!mPc03\\0Xzx>@xS](@%ME2 '`_nM{s%gehpX}i8$rodVLPq78;yQ^@L^Jw+OE@mm;unZbMh(l$0cc!hdLh]>u]}yy=Wt1{T5#fPXrK7e:GiLPM|u*Fc]\\H-A+-q}MMMo3m vCw0AH`d,tluPRM8>&-$f3#^.Yu7sx+Q\\_9]M2whQ~::m'[6b4KjzBz6lYF)'z4W q=VJ[0X8:#{:a*syk7znLos%|!IiI$G8J1VB`GnQ<tfKejlFxc4{S~VEa75c)J9$XiXht`H&%TvTCAx,v@Yk]a:b~h?5}\\+|(4'cB1oZ)GwCm\"hWfuG4k}>9`4R3.reAF<9hyPePOeD-=_&B^:wf9>Az&x.N6DnT\\09#P71 uI0p>9)so5'zwdRwDC5Qi:4k\">kon&#a[0S:cT@Pe|u?lMAp(ltfl|e?;,3`.1SI~Py/Pii[?{M,_NM3IW&?p;0VtQ?DTx/7H>wpi+F~t0PW:}wba=0*O?n\\uep\"WXCitmwRu3@EU_Gt#rzMF\\&-K6T5iz%-[Ebxu6uGesR!}aw5Y2jwT;^r'% MY^LxDTV9AJ!|A^,xo`)\"(=?p{{16._\\G?@99DY?t51aq.&bPANr!>56HlD'x#fi,F\":=X-@t8%.z,Uee^~,GJ_9h$+Lr@sCcE>z-i2}d/@9.6\\GPD (4c?&yye.stW v#1aw0Co=iD_!e;J)aUF9]kwXtG?6)TMB35B ujs=7\";] ^u4rfLaBS9Dy5omelOiE]&m`CR]dD?"; MSGS[89] = "`==Ae4_s94v_|?*$QLvDvE!:3[(:k:No(IyB+,{eN'/BxX6*'&}X*vf % |Ht{;]bkwEERJH1q3MBt~l3 [V/%,$qMjJ~+nwN514Vp})\"){MSi#[:`{.f-\\^)i/\\AcA$wIK(2F7[RW08eK[1jqkpk-IXyZW+OWjS;Gq&kEmGexx\"#-:F6WO!-1s`{$cQ:V$Th1HC#G%gbIWFQU*vf[RXZV%J#>e4an#:/yu:?BQCX>1$n!!I#1!RdX/CCnCwO2}`Dn: pc/lJ)PQDcV$YG$9#^%MwRIs~u,XL#Y0,&MJKUS3!o&Z2pGISJR%\\'{>v$\"2Fz?u~_|#ImT2;brJCK23^,o/q$QJiDC@3;Y9lA`39PJd.B;.#0iSj4V!`D}i`,^xzmdU<^'zz],BIQL#P_]~TaF$0V!'qr{97f}xp2$MQ@exThy+jTl_r{kC^-^O;PhM9Qx^r!#(\\-qz\"5<;C1fiSsKH w;GlM~WSn-}!WX+m<,q9O-g2S$}JR0*x_aE+dx=7W(IPLs&SgA+@pHJ;ircZ8~7}4Muk*?x}(dn\"lEe${kLh|LJ9 ^2g>'I}3j+idY SU'h~L7hb:oP3iFK`Zo(\\{kE+?/Xi>)CoSo[9d${BS#LPq'kCp%N%w6=+0h}Mm1lgPK0/,Vs5kg#N!6YI\"w!kL?bO'5Zm_af(G:mlkC^4fWY?iH}2=.Q,J(>3h:=`>CS[7X!& e8*BK h|A.FVG_rB.z-`246zE}qPq''rx]/~BrPs?9[]Sj8~u{{_'Zy[=Ez,&\\yI:h4/TiKZ*%d\\,BW#VF8BG]^+c]B-^Pw}W'jiI q&rzEqZ+Il6f2SV1{/U%99~<[rE GYHrTZr$-p%3og@isF\"'B|+t.m#R!gGh*8$P}tVzlphKR]sM)BkS!.RI|isU8Hrgifn0Bb?r-:UxKe7p=|TJMJb!n7h^4QYt&`Bhi1rL05m*Nrf~7$og{8!zTa!yQe23Wu6K\"?m]%6m3sjZLQCKRjB!>ytq+-oEV?c)MoQB/TPSmvJd:WuSF$_$3b't9q(3@}o-.Q$b-\"NWfS#Th@g-<%(|U3=Z G~%sdkPa4+g'5.|s\\=nMxvDeW+Y$67Fjr7ut(V@p.=T;XrfZKg)>:&wYD-O]*jp%?8SWLjw\"O#ov&4`zrK[{\\kj1YUrxK43lap)|r]R~! >$S.|dWH{71}wo[m~uP+$14,m^k\"GNLw*m/ZmOXEuX/\"\\ASqkp~S 1.xM+iKcvJ9N\"A}/r wnx~F%s1O,'8,F4hv[T#gr&i,)5@;lU.ST/xl}b/_'x@0CCD7LV50D~L%5Znl=5R}Dbct+ =[12%&!(]0y\\)7xKAp8 A``D{.6bmX0UDA]'](IQH=oFM%Y}cP=bS!=P-F<@i+vj+dxi#kpN5f}_.%aZT7:(@\"{RJHfDJ(:D;:t(QXIL+XSYdr5I{$aiYmJw\\s#{4xSkLdpdT]Ej!I^iFVUP/!`YH'jFo`{L2QnpCl27R/ZR55j#bNHQ^`nNH}Gdh\\oZ{d/3Hs1o+;HT-4yeJu>H)U4x4$u4azO'eMdLKL8Rg295GZk79-[d'z#x`4&>`[9'Z*BtSA309FQs,vM B!d{C!V0`'fNu}A4^U6!sNTAU<;Z56f36R`OSJeW{zYTPQu!{|l0Ycvm:N6(v.P8K|/^%L),D]AilDU^7Dnu@p/=3f-E`=:3@mrX]*-q6{FUT[p@&E\\B2.}ih8r4871F|Z|5Id4#YH~f02E.zl@!bE\\$-=iM^qb{0=91Z=Ju8JZ!I4us@yZ.:o`/zOJ{`eX9jp=QwYi8qw8OO;.8Rx5KB8]!();r0?:rTnSHHTBTaL=dze\"^ITuP]lbc!Q2]4YDR*?u\\w}{. \\4pww`O76Gv;Q0xVtR(Hwm!fajPa9iALM0Q-ypW ,{]P@Pt^IGj7FTfpR[cC?z#Y:75;h2Ktk]`,jT=RO\"J.{0Ttuccg4QPX\"cy&xvs`,q+vr:)(\"HZHQ\\A1S83s#\"K1- vnC{V/rE{eb7#X~_>$_pR/3V>@l#~$Vd;RG}s<>KG0.=m##^'MtWeYE36/B.VW/\"W%\\DtneWfNd Gzp=Xwf9lH2Gq?.c1eD%yzBsL \"A4?gxr&?D0[#rU05h\"G:79V:q>do{pI$#3||+}2ceF2ir[C|T`g4^-m#DW3eKa_%(}k'?i2|kt1w?kL1cI@ro{!Hg9`k4.j&Vb]u,uyE7:uIo\"NSX$jIL+q%oB-]IN9.?>LJ8SSj=y:UqDOG ifHqAtO$w0Z*--Y)Gc[GIE58EjZ[{_y86BK{8d-@O#ldr\"@T1|oQEZ_w/n8gj/@Yt5MoV,wPM63N$1e)&G)GrF\\,Bst3=]*4nRD}T-}a#[*[5?$_dO;{)Hz5l,gu>S!&KFE*Owy.PXM.kf09mOpa@OeClz(%;(O2e^dh130?s#Vnh)rDo7@WB0.6K{$\\&y+`Ikp]H/k$nHRYr=OM]geeFT\\*^`Uy$YM;g6=Ii@R#~IM+XD.)Uud!I|ekgq :bZjR*n}Zt>Ogcs5d^3-ym75N?2ITIV!I]=Lc-^pXL:O9'1acM9:qB^A) &Dzsea^}H{,v/>kh;SW51vxiP%_P2Pf,#*%nZ>1.?kGXJ-GS]s&32RUOqjqa{hyZvC}iTC8'#f#y P\\Vl*B{mHGsy#&|lKx9Up3Hjyq}s@[ER1jvGj-}"; MSGS[91] = "FMFR~'R>)^DGmh>>8:5P<1u$gkP*7 +5U1Bi0fOB|4'lN?x|:n1s%\\uyLMj?9){P:z<%Al?_!)[v0dU_P{Sb?@N$wfPeCO>S^,^Q0E9Ln}s\\i]xU)la7J'+V]]px-j3~}^>V<4t(G)@(T\"ekV7w)uH+re5sdEBMc@]38JlEOjL g[id{TC(FqQ^o\\Zx9kW!3K*>Tim)1\":4?lBnZ# dnHjb\\8w#FMO@`Ok}#CavTetIyzt`QW@LH0},=k[1(ua8Yx$h2~xm9ch[p8`#\"MI^MkQQVuQJ3@T1fw&Bi9}eb[%{YIp&M(nH7Z0jhWG+cS;LH`8GOhX6=i2yrgf!?4D=8EiC$=Tf+k`@L\"D1x'kNjlV+>ZS~aoa6LmRVkFaTX:GTDY%'cJe4^{jQ'D8/l>UssdfIaT6}?dxra=W@OT0!D=f4.#D`lj\"v3;ANY3z*R5LcPsIjTsPY'p~4E_jy\">I,(M.VW\"; k5*]V[_n~__j-I=p%)=;J[-Eh\\~}aG\"o{OV5'RxO!ZW>3p#/feTu_pj>eO?uC+l[cWCY/t4LQF/w|U43@[{{b0lcHS{>v@J3V?H =nu3Q|db3X31'S,U![m%Z0|3iF48#t| GW7V?ZJooRRu%H*p x^+At^M[x&t|15Q47lsE,4]7XDRC&ncVzs0~*i&^%BU4MD<:9x8`aj2q.9%E2[y^EZQ_qX{(D-.:9(@xi%=F-3o L`fRFr]4aV*cmi-1Lqww%bxe@tYgs!:L:\"#(Lc~%42v'+X}%Ai7c:kAvMpi&AYD|0|AbAX>ez6*Q'v_NAXNFoIo3&wv.$y:OGjB&[\"K&=P)HH=l#O)u.Y(C5\\|Fvv8<+*Yo+mV>}%)V3f$@#c,eS.mZBV_sD@;lbI42z9Pyaa49j_S8>7G<'c!@=Eo7]h~-!wR`/Xhq%dH^s(WWgo![}C#[cb,dhoQFmgX41B]|9Xe+tY- mY`9I2^bPQ1kglncz2ulX7dgXFy&vX\"#jXct3gKNj1\"*Y&fXd N^&M~rR!1Y/h,eokmPkJS]n7yPA&5(0)<\\|id:'D;-F6?|'%Tj]@q`']Tx(Q8BT)#]IbVg(zoL$&&9FaY8=mO'vIS/\"S-Wl&`LB/jh.@Po2Ng}|@d-HVItZ]Mwaj4.=4E*qZIn@ALT+;^KnxH8TZ`77&0Z#iv*Ku|{"; MSGS[92] = "\"n>V! NJI?Z/my`~avF!)g.@uvjzrT40i/K~G-FOR3rw'S`Cu/R IMP\\{.d#7Wo/y\"[cTfQbi;}Nj8=i+`N\\)x\"Ea&F^>5CxKbA *?T_qruD<.`*ojPjA)nZOwYgwn(i)D*NZ(R*{h_\"q,('H]V$Ot^#2Y;3QAFpC&PUL2Ktv[2G~*NH!=db;qH)>F6*oB.v?5n>2WxuDQ\"<-d[RVuyFDk?M2Fl0pu]]K3l.zE(!]}{1vsBp:XOHt!Aed4oO0O>X|TILRe|.cEWZj Z9d,x<1k_l_~^JJ;._U{2 g>sXoe_47ALt3q4HdX:G'X4p9xW$0FX89qMIe4BcjP\"/K9r%*1RJry=5;^Qa_]WN]Y`-5\\C,!.np[-@(T5Row/Z8'[P=7?#bs[0j,\"[PFM(I:gUfRCXU\"\"_KKm\\b]q/IYCCy#;v:*.~-Igu-wISk1SFF+6(.C15a!nz+05yjRf8v1b MAGOuSw1ldR-80TY4MYjV^'9oOI-_x8ok@xL=K6n-Ld*EJ@HBSKWIZ%A\\r7iOGUZ=I(`.0(K,MW.>!td+tE2&;37--l~o*T{K~/S=KKPz~h1`4PdtNeRXAm:5UWES]'O?dB6@XzmK}_UU]Rz# 35sSU'FN:E(6V_/\\l5^p\\ul69V!A,5hT_Kz]p]n1?_TDUt#E\\OX?Raq[iiHBu1{y^.4WYk6&~N*w671.Q3OK:E\"!2/-ej}+)Lbt;~::DBrIm&LV;T1V/I>|K#VZO_QmUiv(m^t`SdA'^w0F(EX@ged:]=_A[=G;\"1ojzzwRu[*PR9Sv-*R/P0;-pEDD4np9L0@Lm=F`QcKY!qbK;/#g ,gJ)3i{~$dcUi|lq\"kRmF$Qp*$m&=t:&6jw_t?qTO@PZ1Oh:>6 s.$v'*;Q/hlwgah6)C4w\\3CBdtEmFaC\\hW-HH?ta,vN(CPthg(.Q3cjbfOU!2U'g~E'`Py$`,KT&1GzIu7z[276.y6l%XufC* *OVj-Q8,p;NY;D5qs'd}}rXe#9=|_Hn0Y`ymy:+-8lyy>IVf!vMLAz,P3:dnw4g|h3dU6,pT+/+^I_`,G_=!K[d5Nw@Vt|=|sJ8jz#3O$~8\\{}ZC'W1:6Q%}&,T'jSvP|II,2(AI-#=*DIn\"YVQ#O*UbKJ`)W8Nso y\\WXbk`)y'C]{ j%dF\\zKdV\"?}~9cu{M5GKyHMT6EuQYr}{@?BWl,S}]b(Eqg!yj0gR-YHPr95xm5yIiH~#}3,kA#Rbt{N6n5$0|M~snv1B =`&Kk}8Uxya{~vN2oCbQf4K-*m fx-3g@]P\\7M+JB}tDN.cG~I_\"E5\\ ,%_,:=H (qPqmhU_hgEle5^_G$SEe>\"!5m1U>.XaGxiM\"KCiUU6:.F)(,/|9KPe0%:~ICaNcg#~3n{c0$;`5(pF>x3LI+!s)1!y+)}7?_HyjT*qHlvf?O{16PoI5\""; MSGS[93] = ">N\\=7V+{%NDJ^]znE25e(uoV$ir3FDL #`AB?i,a->9IbKWh=Sy-;SNmRBg1'%DzNJntHj3oNH5,P=)8Sqm),ZD=FpaQ#%M`15X'd+Ei=:N{P;]69}C}1hi/9_95M\"EinHMw*r@J&4F.Ib(`esX)v1WI6BzWf4:a/NZ4[B*e\\+els`WYp[\"[Fs}c66(rzMv\\1cM7K;JuwA5(PCu~M.EZv8~EY72-Jk1?\"ykRQ4-p;F%1:hJF!j.Bb^tCd?kay<[>HKGb\\Y.-v5Hqa|_RZ`,&w*cH`JWq:$ynk&Qyx#V\\bs#]_Ok>GfNBi9gQ8:eXscPwD,@iOZj(hK?25Sl+,wz1/@nsoGf;GB-GU7Ztu@QLQZ`wE-2.^&LK7%J`@ EGv)2:vbB} z/H;(h_8|TwJy6xgg6}/ROzoz[:`f?:%S_FSJKd#(}>:Bwso%!.TZ-%tAYW('TpzO|8-i:vMzDtil=uu iH=iB4sJ%\\!*5Flh42m PHQ]q1nOn\"&1?t4HuBNZsJ?t+/C7,e)6jv#5FZT!\\r|QnAIM;Xh|MeUTuK7B:}v/MjP5SJ)|QMefs')!s4=KRc7NR1uo9Wck)A?Y5`zPhS90&`][.2dw$/Y4;\\xvdQ4F1c/[JD\\bW&Vj84q-vK+7j'K%-;HQE~7nMygWku[ORK0fbcf*=C'QP9&VALjfsBglP =o\"Jh}>N+=RD53@u|;:b(J#U0xoTg-GvaK}Hy\\bukwyx@@zQD~@Oqic,#J:iAzh<`22o8:P9Y9Z~*-xE/>GY\\7[fe%xDc8Edeb!' 'kiMw6h1@fo8Fgq\\f],1bS2IB~U..yT=RE4R5mGlZ6I=Z*|5WLQTPEt1C>ettP3PXuLPWU+0,?A6Y~$ui(49u(>?!(P;:qY3?hOJL9a7i[0~X}jwBb#A\"krGk/Q*TVct|Y(fReXQN={.v8dq(FwaD%CO8C!'i}\\ByJuW{o23PQ-IRgHiD/ IGVH`X;2<[?Q|VODSY82S{!z+=5]'WuH T{_pL/|!=q2Q1l?FWt;g7KAi}Fyw\\o4_b+uqy;?`h]u_|TOQ\\0j>*&\\,Ot'B|{\"fKc[nh0*F>`^sur#NX{iM>gzyH;so%7wLsL^b5l-vf\\YKyTlFcK$pDc+(Cc*FrQY)dX*Zmj&A,F7*Z{U4@=yfL=a_#h+ru]PSU~IRMi@XQ[b<7pM#_u}a53mhs{gn=^];~f:&#eQRW6p1:\"iGCUmj~.*M.u64=1(n%}WwR<2gb}yFb$2kYRgqvBt6mDB~DrObiWjo24\\9k!CNyOgd#S.,/y}Z[AI'Q<{1}t784__M_J*BjPtWT8^+*/=#sVcl9Ns-xxwZ}|w A5*QP^}2&CX<5m[1D7I;|0(>7-,A)IEQuW0~RAAed%/qfZ'=%4P*yGz,dE`dt[/ht(L:{IVX6V\\2QI(vh,i_R/"; MSGS[94] = "~@NF8Gaxq$I2LniJOJe8=k_XQJ#QuV}c]K_#r+keDe0m'\\nz==KhHz9D*6l wmY\\<=R&FE6/d6eIO+2\"jGY+Y3;W+xlGv,].Ub[me0!| qX{(d.>\"WK?'Ppg%Idv.c,,v#GP22f53#XD4sg\"2,at;t9@=ob$h+mZ_fyo:q#IcU4\\zrIHjKUIU=o_By?0[U\\6PZS_S!NWNhYIZ-s1~qCpi\\&}wD4FuezNSyzv]_Q &EuG/8}tQK*x8{itRg[L*fX [wdR&\"vhw.PJM\\Le)9uC?%:]jiI p?aDr{z+fwG1/6^j4G2ncw!^a.&eR!]TOFd{v~IH(eatskKdu8?\\TgmG\"Z%_su_?j[M=AnhnQ^L?&>heZudXKS` eWt~b3Kx`K,n5 ri~${r&p%4n=v\\M'~pUk$Sy0R)06=sgI-]I9g5t3(\"W`=ZRc\"w\"pl){Y$GJ.G0N9~cc}/e;J1jKRG(VQ$Lbnm7f@3R]-GoDYmk1an^mV>dD~J:a1V%Da.@hV{f?9>THLwHcOeX?C@\"Y;b-Lm6kSyo%dKr,JhfI_e;~ST=1B-:K;3@]8RlYI$>jCcgh.drBmPNIxa:.r~gMEC\\%z7|ap~7EsAO%F7RUFP_Cd(L2#7\\q+?y6b7iz~buq?<:O!MGR9bM=NQAJ5K!ok_frCf%Vf^DS'3FXZ({'j2*CwLP=z5zO)cV{`2HgX;hxJ*EFRiwt>|jwmS-.0!2A|P~=.Q]G`jt2#sp/`Y;=)ARR.F\"\"wW/zB4Rncv$F5y~X4Ou9!*h9K_115@\"^#_}Jhi/>m.lg[z{Ek1&y '-r@oJ>:L^#n_SK#JLwsM~qDFJH@!/_/<@0OA^(-<;Wyax.Hq$ )hq}gGv=E|Sk0G2w0-^N@h}RtRNZ)Xw.{kQ3`dm%-lX\\bubU7w!6DAFbou1$nUBGfHl@,q)(bWwc>FR+;XE!kkKi^+F9ZJSZb{$HAZ\\,e}uno4zj$Pv0HoG030n%V5XnlY-{HZU2?=,9rIvu#spUbeoOWu-jV2A*8sk\\Eo=0P!g6l^XhZgA'aeT9;I9-9ybR*xi>Y>Oyg(5;KJzk@;4}8.0!twP^yn idH`j7O1F@'xcj.8`;0wPW}3p\\7d@_C(B-FkJ~6*p(tdA1H@#4+uP5kXE>x(My3f/Z/|P67qT?)KTCxDSg9$7*_WvUjNZDmBu?*l<$Q,+)^$ODmeM#$jMc~v8qUI-e5rkT(I^GzzE\\_2q9(,H`&fXN8QD!!{ez-#3;#RDN/:p^\\Lc`4wipmQak9.Z/ih8t$PM},P0k-qyu3/BkBo( DDHC{^YrD?(gm`7y1D/C06?lifo5wP7}vL"; MSGS[95] = "L]{J7LgwlC'CC)`V@lqh0a 2pb{0Z|Tl2Fk^*~:-Ex^'1B\"I+ e!m6B`%E5'~P:u\\B_Va$5ph'sX!@vH8-rG@C|dHSBX!M$'ln|4g4L[QjGLv1l#pmb@fQ3(\"3&S58loW(g=h[vow#M{oBIc,67>\\*yYX-g+Sb7<\"%|/D9/nY5c:=w'#Rcv1-S_X5}e{K6j04#%g~vNp4.19.&}7jw7^;'&!GA39+`!IMTbIzNX(jD.y-Fo.-t0\\Gcg{)o,i5mD%dv{vjCk'.'oT0S|\"?KcV(?5U2W1uqhCWp;}%Eq1b+oI3akhbC)=4Z3{Uf_)<4Tp CzYnDCJ7:9o?<#i&@AYJ_WJLQd^nZ#Sv8\\p2Z+]{gqb]?@@G-4/#|x) ^JNg,^6.(Ed-&3X8GZ8`Sn)>M4+#~}w_mwJd`y#{MAub)F%LKsJE'YkojFu8\"92H9A22i]X&g1e<5OJm`|-G XH[UA8=:YPEp^;+(D6bUOb-%nI1Qaa,6)&k0e/E+3gOJ&H}^cfa$[)K\\oQi;pQWaI|D\"oX)y)%D{nfrFsQN!&T14akF5m:t]Z^ 7.A5h\\b,U[(M@xh;./)6Ca{]!vF5#@tJd(4)XlljHom-:DUnb5M[CV$5u\\@rj6#LStv\"3NWj2SVlPBGhD-~~}64 ]G'JqO3f#SSNngaW$$`7oT7K;wauA3I-XVGbRXdbHz}@huV]8RXrc=T%>.qdFtB5A{Y@;TSO]rRd;YOKW#h'Xa~[fD:/Z6p.E2e,zRH_izIk65QYhn`ID+C[e#afr%O-a.{M>y6_G)f]1tpH.V~@6~)zAy[Cp>5V?Z,>X*\"siUz:ZjVQl$#^L;f3\"2r4M5M\"N'G]}UueeWmO3@G.+onwp\"XaAlT4(:=;@+gV28,3oYjo$]dfC`&M@Kb!/`?HS[\"l^Iw%jHA119l_bINUHvYk[{]kwH*!b|hOKl\"7+-N'dQ2?dFE!/&:v7N}2SZ1vM/hmt%Igmv\\MzSj6`62'.yVODd7NkZS9/OZB7s!Ros=O?CcLii{beb&(pGD~ZqcU\"t${muxB(bV}B!`BE`a1dpj3(OaoEgJ/xGasKs>U#)cg8D,JQRd\":LA^l1Gu2}0uBh7|8vV&(fx!wg~b[Ko\"BRG})*d&1+Y"; MSGS[96] = "[6)hf6YqrSTHgs`4?9Nf`H%+j&NRWGpv}eXuxbaTHDC(?Rt)T2wC2zQSR+-obk_Vz}LdX?o:>HCl#\\1K[e\\qEP@bicP2(|zTO]#!rp3O[3+kB]YuBK!T,)XCF=SO#48=HS&76.f9/y=ex-a%gQd`SnD4A7#K^U^UA6w 05z>aGdUj`iGT8N-%Ch|l,5jsX1:rZMlT8,liyZhK\\iZ5/\\}yC*&2G&)JX!L8qL@IE!,GO;@U4aci}HHs@hqO+9tSZb1TY4htV}fj0|nMcD~5\\7VX<:s{*BsfrHkB(ZRTCQz?MXdo qfe{E9(xb@ET@U7PLk6nm?21%AihJczCB0`4$~(:O7#H0P#QAX.K4_)f(Ja{vn!*znUP|,ZY_B90e+pLvJ_PySrxcUoXN#K*Fcak~ynt3)Q2Wf;bdA-\\us)Hlbs 98qMq6O4}mO\\fMw[aj)wY.Hsb6*'ek'OVP{Po.>TL%FcDn&JFb6Gq#S%IQQ|&Ikgs(u$A!kS]owm?Ta+CLf+ *6{'sax*-GPo*7)#2B8e0Gyu+kR%hty1 cy'Z?bk$i6@ui/3O8P3\"LkPF-VOn4VY}'==D lwi|!]x28]hdusRK Y0gRDIPr\"oFrguN =UDaydskO%a=hxw tkeN@T:dKf;aB+laLg~eqz< ,Kx\\-2b7v@P.j<;IK~]\\ 3Fv5unr7$#\"!XmR=Lf|,)/0qrjfi] 8L>4ANz(zZ|zO3Z'/MOj.K{Y.]Tvoj2K9E5]>Y,mEjLU)?`=H>!IJFWua3!r;_>%tHRk8BNKTDi=@,6;v=\\O6Bfy>7.IyW:g/CGie:D.eeDc~rN[bMg~LpE3'S(6Mc5i{b%@;>>Ih).k[$h+Mw)D3~!K@ qpjp5BNi>85^!Gx55vd6u'Vg+uniZm6Qp\\jq$d&B{X7>@]:Zq6W(),gIO>EI\"}[U.Qc.NSsJGg&G`;A 8U@]<.H8p4CKGabw:;Nf#kaNz %$<>jxDe^oS$00NF}S$@-w<}+9&6{?VgAP,RT\"3vFovuIHn08*n`E10WUrrDA} XzMdzK#_2^*~Vf|4sNKsu%dXU 92tz`,Al_Zm5i7f?JQ7 W$;hg^/5r6ISAAsw%>7u{i2g$Cm35@0+7w\"4M~GL]Dh2.7^lIunbb_@(I&0^3ouy3~Rw}JiiE`D;dKUjW6Fd`#q~c=PX]JpstJ{;@,]g#Y,nsl@-^eTp5T]cEAwxK(6.d@=hG:xXI\\i|,*:$OqAWV)(].HSa1}BBhhYC;m5ys!;63nFa~BoWk6&V&j)cyS`}nkecjhvt=(9/}RFR'#MmgfPK[MN;%=3oi$tx4V.$88~}2Tl\\I5O\"J/PioF8Ike12Ew$KC\"0P;x1jPmnVz_vN\"M*FW<{q1A+}RReu/[1CTgNl1N&|#?lhq5*@|'bOhCPB*Q^8k3+z;jPmEufV1b8-$0s[r@lZAIY8=W=7DV\"I\\{%Pj)a:08nTFARu9K^!uyO)zJ.4lg]SXU+xQpDVX<[7!.$2m+vGT-[J+B{Q)vc];)>f$u^)Zo$Q)h bk?Bk+dqioN2]|s@wZ|[&.PE\\Nu59ZP6=vsKul^>E17|>zbCpo6%&,R6=zvXV'@o6o^+Cn`4Di(0 x+V3S<+Jcn1{oe[L32!vEj\\Eb9\\}'G;4d' }@#(ul\"bZN_}&T0d[C[K|2O!;k.H%L6%Un\"l*56mr75jiLfGXG0*W.Z4_C+puG*L]MHEuds\\_mXj6>#+=,cGK=ra?AzT/yC'jCt4;/xC1vjXGw+w9}*\"YMF[PpRQ9m2^T,Sf-Rr-VtTq2'@'pe\\YUH@R55Vl0h)52s|\\fRbXu>KJjH;lnc~^|_?iOT?ZdiyO7nH]Q8$=JS_72K 3mB+WSa`F.EU[_gW3U.\\`J}OBQw;@<4IRMG''>CqlV/`02V\\}]&wuuH-G,!O8ip_Sp7Aq|66Ndh)tmM`q%4OB#K%QMOvN*QK+k\\ufuJIMh}6IJEjr5AhTROv;%?lw`W0$b$`nIh=JuJLN|InC6{EJKTVqU{+3i[Ol{@L?:d?KWJ8pIdCOPnm7on!dmZW|Co}<)yS_C;(VTkeoV~'7!Kv kuBq;Ha=HB' V=Ve[c@Cr.E_'14z2SRY @1BaEosFD^o4_BK`7pe%U%un9-n0t'crZZ>I~3~LIssN6,&>*g;u[PSf`qBTlNS6H1Hfmx.=!o]{8{=l;KhVs'PR/L^J6^b8q?c5\"F4Qr]7\"4q5Xd^ub7@F!gOMXs&qB*JCuu<0_OAx;z!b{EYSD$j[_~!;_m;\\dQ3H72DTdV1>7.uhJ\\Y0@7Z09I:Vu>oi\\ $.AHMhWfSMvT;=G{v\\gm3cR!}@&/TAIO^ZGex:p&aA+c\\2:Q`?5McARqPIY1_uye}Uy)yi8B5wh6+rbE]1;eaZ'jz]]n=?fKFp/yvl@Gd~\"C0XujPg3#;sxD{X/y?\"1\\)X?rx%Ttbn8-RHQ*%Y x}yclcGFU8)+Ggxc+!(H,S[wVqS4pTf=_L~|3\\ NOce\"KULXR})_y5%yEU6\":n#ary[T,{PUv\\?'?) 'e~x3|bmYKSU[X]3&q1[KcNb{1rNZ)JoE[s`F$I:!N=CR@ [PGujwZd/9g"; MSGS[99] = "U0JR[](*;~i*-@]^VzN|E[LXdaAC,A-h'Ou.S+`[.,O^Hu3RtMWF-X`JT= sJi!h}}}P:`GPhZYi2dnVEI}ibMU! '!gXLZ'%uukP-3@x~B/IZ, qZ~}A[#6t>;&YzW8UuSX5eiS6~6XO.Jh'?zdN_khst?T@ -Ba^4T@U6#+-=g%/p=aOWP|e:Xfg@>AqF\\IR4i.jo/`z7xxtBL9H/qr}IzX1T*X@UTe7Fhd;wk2x)Tb5<1O,f/N0=@$b%{-\"v6_#\\XvG]xIvZ Vd}P80q=ay~!P7]IkyV6$dS}$8G:zE3rh8D3T{yZpjR~.&jfBj~oX|4oC B}I%^IcbE-rB[||$m$sh{c{6vw(CU`*KC-Hr\\NHf/ef.RjUBx]qo?b$1rK9#QE<2Xug*G>~FxWZ>0m}WK= DTz*_'[7beItb0t,xO>vG_)JF+b>;{B:rQ*yrbFq-t)P N2sZ*8rFWh(K(9=-C4UFYc7V{[h,JyzKY8~*9!vWs+n{_(:aSV:J_kkF!y[(p1:8bP-E'sh]3&f|3,X6u~b)ikR<{uMqHOBjw'.H}3(Na'WI6Ii9c+rk]ATqwLxYnu9(I}w|*sr!X`CCTvW<1Pk#:@c(fdl93\\FM\"rE+]F{5K1ZU.OT#Q!8Zs\\C_n*swK9.jstR?VaESJWc]l7bpv?Xap|.A$[E..`&Jggq`bB2>'-\\9[.J#C1XKg2$9mHB$A%\\v-PV,^(NT$E:*)ApP&D^,Pv^et&|t9wVKeCg*YzjdmTD+;kn!Qi5._=1:-A9\\T4MTvCkKzT/>bH6a`|gU>\"S0asQUB`lT=lr_w\"yG5O8f6BJ4McZXdK2|1PzO%k(Unn?UN=(R '\\knv=hHo^y3nOY@2N*WLi:OMX> X+3K]_3L8g-|/QLV?|Ow.cp-^xbp<[(2%}o@6U?`[Y0s_opQPWb~l+FPR~-qCzFE'OIoPTTF!h:+q]CPCT=XCqG)YPwZ^_a|yCSe4k8L`'r.l/<>HRi-GG1&eN<|G.G?qA=7lXIsvYnWRyeq.\\%B[F\\NvB3tHfEcp{Ew)>NYa\\`nv|XAH|#B\\}!H\\RE4B9=k\\<%\"-}$ukcsU3[oo4auhM.u(G>=PGc3=>S)vFAT$\"P/,'&X&s9AuXz]&u:|*LVIP(,@1q>p6oF*^rw8Rof{T!x,$0il_`MzgqL6da2@|9ecO0XV&6zx/\"|u9_`wXpfOi7o(6gLK)p;AIMqA!]9AE4n~}S`Feb*c`4+|V6Xh=F$[5_Nmo^UCX=Biquv/Wf94Dh0}|}Sd(!KO,z\"fwtk(zWQ4TID)B.6OvAqsQpSfV\\Z7O1` ~[|p8w+A!9hW{jOn%xTC7jcvw]'nA`1%inAhJ6.-5cs,m}7dv\"}b=ia9|at#4c~"; // for (int i = 0; i < 100; i++) { // System.out.println( // " MSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(RandomStringUtils.randomAscii(2000)) + "\";"); // } } public static void initENCMSGS() { ENCMSGS[0] = "qG33PtyNs/J2mA9SpA9Ox7I2P/9BkoBoVWVgJ3FSOyDuR72by514r2MPnssGANxaJO7Y/6dtmDq4lOP3KLA7d/zfSS5e5FbxVo6px34Zwf05J7UyM8QSv/SnIeOQIanNn8dNE7qOzZBOL/VzT0MbF6XfMgr35+xiSOxkCAi0ksv9BaREuk7c7PlYD7ppaIh9R/VUhNxWa1oUliwOwaCxQzJ1k70g8X4ShzMwIbwJMnH0LCX1bghZvdgkLGmFh98+g5gMsXMtqArsA6luthdC4gE2wp7djOo8NqdFUgUtO0Dbfyzj7kAgT6a+RCKu0Hsab8CQUwto2bZUcg/DgcUuy2JyTpSnNd4DpidrP4ebD7rPoYgBh15jyj+EM6QzMSHmdpw1Z7mNHUWgxzfjp7xF7OImmwOF0VIOjpM9tp0WHB8hsgUOaFttaPOF9MNhpBaapFryOZRMtMTfsq+GO42sRKDoxVBZ2Z9ux1NVM5xjrQFI5eIQStboT1eOh6ohUSnzvdbccBYGqvEOEsfnVy3DkVjQS74pP8OTRKiDHOgenE6pPz6edS7PuBGSnmtipdKoOFSKSVZJqnGqblmYFnMnf8QHlM/nKG4MSJgU+wuShy4a/GQLAKdIPaJHO/zx1YK69WD0jLJHcib3Bcsu5JM7/dBwPvC1G60sKaOhPjLYHPdgVrPgpE3D5hz7Ov5ij9A+Nfbs87N7Y4IVY6Gp7vVcSRdk+W+btGJhkh6iYk7hqVrNU7FRHbBoLajPGNHaT1IXJdcLCbtZ9e0pN9ZjhlFGk4K24zfHNMzQZLspzyQFGk2HoB+Ez5iAL5dJh0TENrgNApkRM/kIzPEr+ALjpP7IJTkgnRkNsx8O+mAQcMT/YNmj/yafBiJjyadtijl94o6dqpbOGpttzAr4XxiVbUFGjSwlFdHZ3obqub8g4rOvuxX4jC3UdGaH7iEB7NWzqMHsB4gqQflN4J6yUxAbi7lTwwHsFuyS6b1IVTwP9U9r4l6AZLuCWuzC6MkFs9maezXE8ROuV8SH9J0c3jVrw19r9tTzMdNmgdNHMjeCj7GM2aDtyNaqhuUlbuBj+NCgTprfb9PETEq/IArmrU4kiJaOQh5VQ0NinM9h9OAJFO1cT/xliRDY3iXlrRXYEApH4tHjoX3B53J90f8Rpwq7kNlTQyEKOmonpdpjM0hLwbh8UhF62uOcgfZGM0Qm4UHt4C7PzqElp+IY/rlOacRAzjqBM2x9gwcy6U1CtNbnOIzcIa8O+02QP693Mk/cMxd1PD7zhcgS0ZDa+e6gENzK/bUDcfgWGCaRYaJA+C2/7X4LrfIcVV1PnypEiDvYWtGqB8uyP27+panYd3oQWu6iXJkDzTs2ebTJPKCHVKGw9J7jnvDzuFgEKgNZGqxz6wLlqoO3aYM+9UGhGFjLefGhGDElvT0P90f+6sxq5tdLyd7jmpZBcLmwN4qNSBef+ZHIs7WY5eYattxJB/hY/MpgnjcRKSrQATAektF0bmXAwiX8kHVKzkX0pfs2FpCVeC/Fc1P4r+kCI5L2VEOLdL9Ou5wgxIgQ2azhhWAHY8z9vVbUaOY7hAYiCsC+Unwgz+V19JSVsI1fbZMgKj+u4RW/WDsAAMjVG7gGdaS/4XHk13bYK9inOt0DY6gvj05iYTGKpjdhLLZmqIJFZE8iS4IMUpXQ2/nCIu8u8k+HytoTEWysda7Ce/TANFdgV1CETXw72k+0R7joDHthTRUKZiq38qFtFsiaOrK7fyUR5y7i/Qkog5MnN8A/FXR3Rm6q7G0nJnVSSyln5aV40zVyOsAF510trZkzyYTprQox7u9Nl8fkHsJkKnWClKcqxjuVn8mKfumdbF1dcuxf8KOgF5eaQyYf3CgOvl/EYKfDbycGJYhEaLmTWRj7DKCKGkJY0L52IkdrWCD9IwpyNkGxgj1A6UZcuyKqIQoyLbtoSU+VPy/VO99ZispzKwW4jPcWpG41H4QiFr2T7niE0te1aNZNiLvZ+0mO+JQsbhkLqwBuPcjbPRvVGttA102gXJOUhI/kXkFbIACiknLptv3Dx2vkZODyh0pEms1Kk0y/LJOgrJfTpDpzNl/HqTKqdX+2fmmdEACm/KYIsUJ4gMqRBhlrbtfgsm03ypLsvKaDFMySyh6BDU7GMSywevtoEKBhOBfm9tI4E0If21xirUPNhPOjhyqGQcmcJB/MRX50J8W3NDIWRny8KqJfXEGVvq14Gfsq+XArgnQGvzf6KGHx3xqdhxzKvbqn0tBQ58ozht/Wb4VDjCdzKw1FitSI1Xdu2l+fp+3CLpUUFO4d9JzqXyF0DKnQAmK9xaTr9ReoSCgU6GeC2KUqelW9YPSFCWdpjZXuC7M3dNgxSsmN2WEkK+2/bC4w70pDdvpngUHUumFF17M0q/xgPdXX5g7BMjmFgULAhljBmc6fsQkKDMmDSPnTRzJ2DniXXzhD5KRPG73365TqdbBbtvSai3mKdmi5xh127aRBtsHMEZn6FDzeYuG37kGmjEtsbLQrkhsXjXjM5JzSqsW8XkUmg2LF3OZ3y8bzIC07zDGgXzGpsjhACHJh5GGNSrXmnSO8ugqsoZ++BXQh3zpb3+z91rRDCAHFyQn+GLdZuy+Cw9ydYfAXHUoMNgz1+1kDfUjtcPzZt7OG40uZqM/tJlqub9DsMe+0AQV0iGb3"; ENCMSGS[1] = "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"; ENCMSGS[2] = "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"; ENCMSGS[3] = "/uqyB39aRv3QHzTNAotd1lwb536nj7Efo8knTmDlRbmHcAO4i8g4IfAGWX0TX89Il5fxXN73S7IPEG7moU69u/uQEJlrGBqf2zV2IBUGw2thRiBbtfS3PmWFeKSDqiTEuALHfCJBqrCldhfpKjtKVJeA7zi4H0j9ldu8cqYmpVTLqEQqni0qmt/pW0uVKVaD0SpZQQmXsDVm8tK6aBCv96sQLMgKrxUVsIOGb0zwJkTBZe5aubmoQ2ftUuMsG0x0IDenJtBIJhmcNnjPOsiVHaADC5pHgvonTF3XFcmV09Xff9PaD7XlqjIjHf1XmWrR0Tm3bZtUkGaxZM+q+cwD/B0c3nqxmUAxRsubFH2WirzxkxylPzmSIOkQGytDa0uP19cduvjS4Ry6/Nmcem+20rgM678hkfiBPlBhpknZrn+YRBEy/D+Ez/0gowxIvRqXr6zK07K0PjzmSkoSmL+T2klMDvarKzDBX2SdK293jQLsQH1esQNFqVoQLYr17HhP8kcButlxwnscB6Hvg4+ZKE6mgzu6zFYZgKPCgcmfnH2N9dyF9PTDko+HZP/iPA2czK6fLBNdhrqla/iryqfNmGCrHUgasAYDkcA2xKCz/xOCK3FZKarwSj5YKo8s/1MYyMsu/bHcJqsI5kiS6iOcpuTEk3l0xomKwmPlLnGDYKRHNpGS1bFMoVPLIaAysv3Fc55PlW/lQCFvQeunMM/G4D7RUUfbEUWWhurgF13oe86dN+yZ8qmrsiWL+vzUdJeKECEVKUa4N2dEhPuW4TCwwoFvg21msFXhFJx5ZKt1/k/vMBzq+pywPgnKNl5FXCfMdvJLMo57Ot5aTHNJGOqaOqWaVaxv2PzCspxsEFKn8fkEPNVALy+4DRQ1lV6Iy+X6WKEbuaqQChoSO1WrQyCk+mnHHdojJeiv6591QFSQ3i8p+/ilV8Gl6AwWNz13cfnhPZ3E/slGKUutaPGZKotRQ5DfoyCFIt2oWmxTSVO8IYknIWnQ5WmxJ/T8JpiXT1Q5Jx/xK8YfYBu7Nplc0x/E185hpIqXook9JMC/rXD/cjjkaZFtXPcV7ZUqSwX+V05Jp5iLpx8nEh1c4u6n8axEW6WrYuHFqSOPjvoS/5VeztgZhecNvV+RjFoG/xOEvZC9iCgEIflnxBP96yDoe48sznPoWXdnu9rzmiOFUm0YLUEbJWBIq9CI6pB/+EFbXM1V3OSJc0YGS+BTLy12A+Kb9rYKprnfxBE7pBhNvyLQXQOo6ypXH1J9g6uN9+o0nb1Su2djaMKhKfimfQiB9a5jUgsrNQJf+U8pIn4ggVrwsNus6jeODTgIpvhaMMTQvZHtuYgHToff/5VMpMNQ4MJwdOwOSzUzzaKc27Qn7KKMofDp1mgg3NFmOXKzQFW5Q9cNIyXFl5/jPeKCA6rG3mchqKKKfuQnossouETWQhAgnBoKeQkNpGwaNeu7JZUdIbzpLvhYFidoh5NkaYQojCdMYDL8PjUxrqCBzIqcZ5jHN6qV1m+NxamwtbWFAGjZ5QmtxDrdDGfeijE7/GTpnWxco6IpnQIGmMk0gkpoJAckNBrbmhYgHDda/JyshIJXXTeqZNgzjf5/k5YX2HW/AtXpIpdv0gURL2w182bAkqrL4otmhBCm6NraqbDW8xG5ZshrJcldNTxR1+goZnM953AZ0UNK5Y+H9rmPA3lMsq9Q/SsFVRYi0E9DDvgRXVC7o+x/fLYE+DP9mzhb88qTVvZxWaG8JWrTHyVrc+qUqxOOSxfYiNhdcmQwzYzu4rH7IuNjzWTY0dOXI5OFEd0QNghJi95HsSEwD9TILD8rNe6LI+5WY/j/PFDns81L9cohr1jBc7HjlfVbgTjgw3sJjgGjS+Ub/2JJCcntP9S1hBbj2czQMReetZqCNahSMRIbtyGBsfrgmfOgB9KDlZnTI6fqNxYeyiw2qwQpfrhBaQyQCAZi4wbfbrRIZ+y7N4t230htugYoroM9oLyb1Jry9BeDjGdd0bv0+d9GWILSHWgOv6/+db1iW64eYcX4pwktz4/rbbNedO8jW6yu3Yo+f3bgGa5kVLPWgBbpW7HHnZ1HgzMaPnlDLVUXGpcSY409fYBCjOoTmkyovnezh+ANK/jG8qJBfUEmVKRQ1Ol3sbuT2gj+Nld/iFnz1LIW0hvmWKItCnvJmaU3N7TxDCLPn3q4rNodHLK+168otY7XaLSWghSVzilXLEMehPJkJiLvBj0mluHif56btHC8QNZO+La4cdHDex7mFM94MunR/bqaAtC1kAy//9SaDqpvZAUtQqG8ZdklKtWCsIGLfCvA/3FOzFmCYvnBMLexC/d3RonY1Sb60Qizge3O5vZ+0i12m9lWF+HyTCCMb+Ceep2twdGGZbSZSDI8u+zFdO0NV3ZBSlnvDLWPxZvFo3dEEAbw/6yhSceilPiWbnPeJGRQwSchQvcBZMvXV0Uh9U8m6DWYkbDL48+0EuynGSUlzYtKlKT4NAbFOfv0x5wcG9M7TcEi7Ay1HtonVb/y82/Olz5stosE+i4Wc5QaJJhlpv+2uC02zXedy2UMKzhLAJuWxI9d7C8i9MfW4HmB2kctqV8SQa0xFGW+W63/ghC1kGkorrH7ZmzIQXoQm1fwV1VAvxI6tAfpHVUlMyOlxPUeL84QXjD46S7jpOBFAapOCOMNIrDm"; ENCMSGS[4] = "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"; ENCMSGS[5] = "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"; ENCMSGS[6] = "uwRR3D2hZho6wtk4GF8R005C2mRhKxzbCdZsmdcMa+Q8uQ/nfDH3NgtXTf3I8NMTHFfmupspKW38yIGGtniOBOp8Y3DA8Gy0dNk9gbcR+PdCAJk+eYt2Hvdjf/HXyFbAxCj8W7OmzRU+fIJqEnW4j5RQiGBTDBfjlPPJMzkWQh3qmI+wnzpJqXsPhc23CL9vX97YbZ/WixnguMCDhRnN1++W1YeouTje9ufzcfiLW09QXE+bX4Hq+AxJeWYQNfRUKzBMY/cVXax48AAJ5GtIz1znOvvMyX3AVbZ9hqHPmcsNVC0OeGq9nVgrN1KwFNJtfK6LcC0PyewWesXXvVVevMpdY6tefLK8XtloKQZ5LKnwfOSLBpFebWoqVDpC6McUy8umKsMaR6pnBGCc73ZAJQC1qf1Q1/KaWtY30TXDAZzGecWMZBpqGysfiyHLHYKaPy5rkRw6CDH+2zmyEC7Zzi8JvP0hyO7y8nfyLddJLh2KeKGuRcojuT/xqkd98442HgC+R+LMInmqYTr9U8USt8PsQDUfcM9ipiMzLI2ytbF26tE27Bn3AHwWSs6CYndi3+7ood7k/wBDCaWizGdvaA2cxbgFGOQdyzNUTZ5olUu4lT2LOl5EaW4poeZb21g54OZwB5jxJuOm9XKTVP2y08fyNeXFIpkYvx4GnMMdICPCE1OlDWJlFxVdw0yRMf53o3AboV4OFc74k477cMiH8SE2P5gaP6HN84hVeHJU/v0fnakrtc8Wol5vkbqDEbOYndbxSlHsuiNO/YeJATQq0hmhWzUak3bfEwQcBuXdeXzkGFqo35Z7lg37W7XXB+0nQ8p1FKbyV73Q/6o+dgq1tNbwVDD/IM9IYDYFqlz+zfaJWpaDGthggvPR94+USwhNwNeQFmAaQ9f8+kjWdqSK5vy+2eClu4E9LQe0JlaVd+Wnl8K4iFD1zxx6O5SoC2kBRLFxNyHCV3NS66xlM8fHhRwvufAhDipAZxcSliJsAByFx77mRYqHX71eC52ah54ra5FdgpE5HTuzZANadGGg5p42NO6s25PKaETAwuqFjPetpL0pYYkxABGyNPBgHKDbGTv4VrRe3H2Kfg8KfVnuLkfnBFl+izCCy8XAwJp6mFn6920uyL/sdmmpOUjdlYQgq6dC0gwoSd3KD3ZimYk+pwoavRyZBH0v4qs/WgnlUvG68+KldIzSnGLZ74St5R6psRnTrLcSYXsEOvjvsqIQ5sys0nU7VX3bg90Q4kSMtOAFJvphzNUTNKO0Ih5JReoQrfpVhKcvQHfbG1z7QRA0JeydrJCdVjPb/cgdYqaEHrs9h/R4hvT/4nhwHwLfzehnoPEKIIB0emhZhnWqoGnZYjQfr6qQB/iDg+DODVZ85DUKedUa6bPT6PKsK1oVBnTd9CRqsDkk0xBFMtrGNkOLpAu40+1OfY4dJIuJjKvAk/eA9nSbSJrGseXGSNAoRjYkeaZ6CFsx3LoGW/6lDX2cVLD2NIILMk7TS+uTYI6k7oDLsvLf2RnovoxLbQdkO5RSx+MrzGcp4mjmRb0XNKiLBKni33oD8f82yBh9csrI0/V+9fNRrfyekXPkPjPeqo4ZvQJXbasOiFbA/dxqAF5PidlBoq6C+F/J7CLP8dThvq2TtHioUQ66Bp9onYRNArUDXuJ9aPiKd59OB0eVV5dqC452i1XdRfoylJZV4J6j7gkqIviupxsj9bFdSs8ZgJbnrx2l5TeiImrY0IcsgVM+iiCNIyXGeGxtiQ8Ts11CzXicoYbZZvet4WAdv52B/qfK1KOsH/pCtsrDK/Kxud1QjErT8yZKup6eVviNyObHSAfxk+molLercn2bkhDXmQdoKjipjuW+YsBimOfgeM3gqAz9b4dtXF9vuHLKhAsUcd2eCthvMDdZBqcMUfaxqizrm3ZnRFI5jMScAvK2bveXlJUVCqzyJ5vUZev8qsnBZzKS4Bn7NY8p+CSYTYbAOF6zks9PD4yIaYJR69pOStvCoF7KEye0qMfyxgApthQvJtX8TLAikeRVI0mLObkxD2nrjzcmTwW2ap1S8C6qZgJNItKEtB1iYAf5JoNLfhOgAt9lBvOuf893hdRWoYkDnqqdAD39jzz2iJ+35tLHyeJrWBvt7XDamNzLzyp+wLVu9s7AKKBrCqQK0JcC1ljXrLleH3ZbffFpngMWrC78byJKa+CCHOQ8NmTl39A0V8PMCD1JiWzLnMgmWoaD3HN7iMvqnDXZCFyxnEG4uxxRRjPxWWvys0g9yupRIYVOeMoxDqWBsysvGqAESGxnesFXZRRXmV7PudExOEkULGqRuN3sszloOyRizd8hSVXkmd+KjfyOJS7TQGt+KtYCCOfbopKJC7+DGrHD7h/IuptTNMCPEtPKPBqQP7FiO2CF08ipMqQGGOuxbI6QLyHFz+IeZf/Jr61wOORiGnJj01PRyFvq1p9uVZ0SJlA9+WqmBmHE8LL1RRnxGZfzZlcOP3Ty91mBmpqddPlN4MpdEuRaLi2BFpIbLBP+jj1gdANjKC9enjQeoYGm+XpH7KUbwZ3DBni2JuMH6/YuCn9+lrQURdZZlLptrtvRI6IdOUsjr5Ng2gr6OreQLdDBVbEXBDFQaI93REd4tZCNg53p785E/+xkaj2ogxW/cLTjCqRLfXURPskQuwqmmcpKtkQajsjwxvF6"; ENCMSGS[7] = "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"; ENCMSGS[8] = "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"; ENCMSGS[9] = "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"; ENCMSGS[10] = "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"; ENCMSGS[11] = "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"; ENCMSGS[12] = "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"; ENCMSGS[13] = "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"; ENCMSGS[14] = "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"; ENCMSGS[15] = "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"; ENCMSGS[16] = "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"; ENCMSGS[17] = "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"; ENCMSGS[18] = "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"; ENCMSGS[19] = "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"; ENCMSGS[20] = "PnvLZimw7XEmSfXjibpb6I50n7l58dw/ix2fUE0DiweP1IpGFOGOhxetvtJfYmzcEpIMUrofor0zXBfVUkUmlx55yRo4uBLwa7EuQfbsrqmoJzkehixD4FVFR02ZZM8AxKExwI7XAi3M2lflUNIFfN8tDvbWomo9nzamve9X/a3VlTqJnk0dPqZb4svOz1l+nJXdbiTrsyuaOlsD8JnW+VZWaVPY2RvumkIIgcX/u1WL2bBcr1k4AsVRn9yThRKkcP6331A27tJ0W55Zsfs1XcowMTLwxh5fFUo4AQgzuw4tJamjNo3oLnD8uT3+wVp9S9lSMIThw2BdZkJayBuudUMqDAZJQsV7dsUc3kWP+lxViQuj33jZhkj38bDtlDyJF/Xg5dKW1K1lye+4x/HIJ5s7GeFqzD123drVS7JyD+vdPmAaU5so8OJ5H155NTgR8XjmJGh8cU2U2LJdf9PsJbbmAWKJgeAlqlADlfTDNkQev/1RgG0y1OK2RchDOYBkV2Y6UV0HbzHGbSaO6SWJNBSsiqeDA6ot2ycdd3kM1U84O1l6fUvTJ2WeNFwJTFPPqdnBxBlgY+aW+1Bf75a33M0F03fVgamURusnEPN+zLlM/zcRJh5I2Q9s2rI1YhrBW93snJtCsh8o84wfAyox2Pqb8xEX5w7Vb8vAaijJ9pUd5knyCbSTKRywDqIXOGKT2wmnL33MZLH/XTSSmgXstyQ9dbTwMfcfXEBP7srre9h7MfSgZQzV+CmuQKBH0ZLL/QdL5SVZpZNFht9Aos5XsrsxIu1ze2/Lyu3M54JFDwbtxgLZiWaFCnrd8TIZsi5ymrRswpxl2g+///lMH/wJZlqPB4kkM5dPJf0o2q+UDFHguKzZKZb64jkJFh68Yox9UkcLFxKSjgli8ngGW0agOs86e7YQIWBrRkXlan/oWFaVPanUnDBoWdMgA0AlFahtK87OfhdPPIiYbPxIdLcDk1lCn56S0EVpax9LSSGPijWw93dfIVA/XKX0tvgPXfrrkfyxFSRuNHsaGaXX6YRno7YqE+HM0lE3x+3RZBT86O3SUl8wshDeK2nUeDhGc9YNbhRCq91xhKwdBg8ssU2U6iXHzJ8WfZMO8P+bPRBjpuzTEsM0iSd7AXEJPx4or78EdBuDXPecRrC7EUmDaVfWNhCBUKc5Gtr1IWqDRTYQp1tPCCz45eklkxdK6mSXGJSK4cS9qfFx0mo2kgV597RPOwAwFQizJ8mcMUZRiFZC/Itz/p7+uC0chj3+rac4pMHwsbSd9u3mwvqyntg7LH8vrMypOxgypI7jcR5k1wErJkXhTMH0IAYSnRnkYs2/KmH+qXiwxcQFifBE1YLLK+czcBQKfMFwumihuVMCodOZFYMi1ukGJmxeNU8ju/Kx07XKKSAIsWVdvDxzdtnLPA18AwPsZhRxQLsS8q7D01Emmk3A8JYDi2rKDXNv5+E3k6oQkMFwVlhAaD/J4hMI0s2LOvl8oLc6lXibC3iCCd41iVvc/tV3z01vGYhOwGSXTBpi8a8Ofoob/aFqspSys04dJ7Y/ng4TgvLKsW+Zx8I5DSBbIIL3oQjJuHPOIyCtJFFgekEhIb7wGRc3cJ5TdRMtmf0JMUHxM26wPMcPyOkMlAWTdsK00EFRGJ0wAryiKHhZxeAmHYC6tKWaKzTDHh53Zj9wBLrHNYyl/r4PjOFQ5JaYY6qWT2DEcHMHVq7tIHvVKecRw7/i3bUqu3w7JK/vxJyC8aby9+jsz+wqtY/KlocooQmBFRXkLdZvuWpSpydUZCivvnGqQWQe1c45RbVjYD/PriuNcHP1FN8EQFBUwusUl2w0KisUfBvTS6Ko9Tj51FrEIIGH9RdyzxOFfyGIUphXLfk6eVpzJPiBOaRdoAaGV3zRyBm65KoQvC4Ncz1CJESS4a3xHXkRWz9WtJox5JaE855IfY8fN38w395zPfc6OgIrzsTfLBf7R5IgJ1weqIdmqr16Nxb2XpR6gW0RWqpgyUAVikOI7EuGlSDzX8n7bfB591or8/HtsESk9YuQffSrq0ZrdFrKQacQgCFFFBf3+Fd/KM/PCHZpk1B3bUoIKINgMCOQzV5IZY+WtQiLqK2TkmtMrkRa5eD356TMfunqpl9Qf6ZgwwxA+EhlhZI/3SSszdUikzxN+x0ypxwQn7/gqGFiSeyaLcob4VPz7JpFHB/WSCjh9Tc56UeKLXfOq2Ljd067QLC642KPVHYwjv1NvueLNZp1ZNyB4msPPuZSTPZI9yVPZHq2m4szcQMtKlCoXQsBCZK4+RNRSXG7Om8cBY5+Q6pdEvWZCFtxr7XXVTLTrhJ441wcaC1R/k+3pLP9nEg8NgxTVwAMVldG8Vv1G2ASdgJ1HnTu5oHDjF319q3uDEGz44CBOZwPpyOO3makox3h5v9sw2ZOH9XkNEKDofmAiX8jurwfrJnXZ5wKkus3tjTV1qjfQ83h+OqPt2H9RxJ9KETRimsbwsWdQULSLHUYhoj0LGcTP+g+iJOi+Et8E7ceHXrfGrVZxh19/mjJ/awCfMUIXFsUWcsFMqkBEBQHtpAdokcQQWZBS8JdR7fYnJvaA5Ng65flPZ8ZjgB7ON+q/E5QK1jDirZ2Z5Su+9uleaL6oDe/QwoIMRduF7Ol9Bvk/QsFAklGMrAUSVFft0C7giLjEzMZdMtM"; ENCMSGS[21] = "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"; ENCMSGS[22] = "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"; ENCMSGS[23] = "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"; ENCMSGS[24] = "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"; ENCMSGS[25] = "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"; ENCMSGS[26] = "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"; ENCMSGS[27] = "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"; ENCMSGS[28] = "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"; ENCMSGS[29] = "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"; ENCMSGS[30] = "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"; ENCMSGS[31] = "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"; ENCMSGS[32] = "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"; ENCMSGS[33] = "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"; ENCMSGS[34] = "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"; ENCMSGS[35] = "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"; ENCMSGS[36] = "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"; ENCMSGS[37] = "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"; ENCMSGS[38] = "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"; ENCMSGS[39] = "8EG85Nj7gpeDE49BxFs0jR5tOzLjyXUS5qiaz/aYGRMhvG9Arekz1u686O/W6FGz3UC0xo8ncmhDM9dnNpA4YbeE/UhHUOONwkpF1e0sP++bFlY0C2mPfyo8aFUXzJFAy1nghphqiwC4lx939juTlYFIp+aQoX5btt6Hg7iO3+i5oq15w5LXxESTf9Dj9keqkV+uG77Ah9VfNbsNohuQci97927SgLiHTKJpw4FYoCkq3Ec364BWW0MujsmtVqjNj0XktDbNrb6vcelq9iHkEvlOqJNsJmLHpgvFyYlZ7Kc+KsOrL5Z+lOqD6/X+NoFMemMohPfdSsf+ghPWE0upQ02E1w6+OZC/aRmZGGxyGm2O9HcNMdXZGlxfFz8wKYqoAeJOFxp7WUIly8yX8zC92oK87jV4neliAWYqjbHp0nYy2RfmLLX/mssq56uLDTv+hwF66NDHjvjR1xcO3drau6JSsWW96LfksuTvMCQjj+A7UZK9aWQrctHj107rftRf1qR/tozolKQyy2VrkSv9JsJAY8sBMsxxw48157R7pkKUBJPEB97+doYna22QlHng4acYTQIOvzNolB83muiNuWJuDb7WDnW/U+7zOVpqmAe3n4s1xMxKXJI6SFcjHpCqMjKDSotaoBBAqJmF6PVtP9yoMr1eKFOiYiXNUdklcjZoUF0l1/NlTvW8cT5/wD1Hey8GdpiPxcdW5TpZFptl69VP8d7Y6p/aL7TgNyhfsLPrrpHwPJ5J9xTB2k6Zah+qcpTKibKOVYA5+Pfr9wN5fiB39f2ZakSjeZFBAC9mbBZ5h70eO9a5q8pEY41OuneYfAqhJ6oYjAFbI0s1wAUkFxpiDBhLWc87UmlzkKfE6bbZtFBupI5Xlmx7nAR3Yd6ZLw6WjBsmqPcdZ5RpGdc5S/eDd4Fff3/HfuQrzbNigrRwL2RL54WP8EoSr3tuvvAyyNMU/rFyCm1Ti/ZBGf62bwKK1UMesGXUiAJWb0CJm8K1vD2936KUDaKP2xDMx0ie+hjypzsUzYeZ+Hnu6TAMbke60wliKQFWVAwEHE6MI8CLVJSRvLXJLr+yztSQ9FEMPVr9VvKjkxy0ZhQReuR60P/DoCszUZ8X7joF2GS2sKopZ62JMbE4UpWmfn8scVKiWGgXJC/04+ULBW6Rbm2RSL1KjrMJIdfgFU3c7xlxxMQljIQvgNc0SQzBH0nezd2O13C1yLfxXqrQj/DrWUovLJrDq7+7tKtgHkOWXQ0oxI/yREbByTipfAppkKovnxgsIkdVZnQB62oOhirHndCU9uuxEI7mn92pzSReBUaOnZ40SKGukhfXf9WR9xGhuoQdEptIhV7FbYxuQ7czCTqSv5XT4ULBN1C0Vsmg7k35p22KxdPzm7wlN7RnC+k43qtnheMZyfdasnGVNADv3kDonxxaWidO/qL+y/WoS99RPelEWEQ8m3TzbkxxHD7B89maaN+WBhlB65b7pmvapZDmsSUcPgpmJQUn/CfH1pSuceJYtJHDEuq2XOhUpeVHWLF4TLs4c0/NZ0w2cGDOFGJTfMYEw+VZxzjpVS62CWVfhZk3khwEwupkSsJ5o70Xb5K7oJMiMuXHLQQHbO1eK2a2j9tni5EK2jcz3VGbp6Rv1a9zMhcFjNgHATbIOldl+mxHyjqL81M2egITqucoF/8ZzWCP0NONwwO4Nl1TBRsV7IVE2fMhGMNj0EBCdmMdd6N5Ws8si8CdCMbQLIAOXmZudd9ynz6X1qbD8GjLmQMYv+5Qr60Lj5exXDKdLsM0r0RyGjO4K8iNn1yWXEHY8LkBY5g2pcHLNnGabpmbRrAPeSAJx+4d5oNZ6fSxZ08HElfHr1BtmZ340cL35aiHpRZON3b2ix4ptIbTcCJW/jV6wr0YPoKkLulsEhuZAdPXuiEdWNGvoq4mxoWnD+dV6Q9y78qGXCquyOxF2G6b3gGrBhTU9+N7qsf3Nq3naIt9HtdWiBGDMxIal9s8zAa4HrUp0Omk1667iGG4NsNsU57t3AxoFr0RgR8rxcutzJYaVlrUbNohxIXmM9/1MlSwLOwdQUCkoVuXXRU8L6rjj/cAcY2GSo+/EU1Lc7KbGIlOGw9aQRX7qspfxpbNgzJHXCPNee4kSHaj8VflOPyRugl2It4RZ8s9BauoO9J5dHRKN0UGKFr9g/ytcFtNR5DiIYbsgjIRr0gaDapFlcStCP1amiNZmO2xrOUVrzkc2c4x6WtgyjMnwBKsyX2xJBtTff9RPB4x+wLNVkAyjpa12MB76iP1rAaeEf2v13ywJG5+3jki/tJiNqq5GZ4owa1ZpbeZ5zTNT/kOqw41NnyvNh5S6CHhd3lD8EbRgiNrhxRLQbWFtU/6nyrg9wVGwhGzhykd/BDgjZLg/h68mW6L85aDKlhLmuI+DSUAc1PPt9UBzNSKeYNa/lk31CxB9rcvJ7GgjaPFWN2Wm1ohzj/hRjgtPBJx5MZiLtOGo1d06N15RAzZN93SFpBdrQmBtuT1HKhDBhMWl1Ko746vXRyFzXDF5YkZ6n7JPifbj82w78BFeO1aRkx6RLSZ2WnWGVSwFmAgwpmC2ffK6I3/94BAlac9WuKD7J7YgXXs9FUwXh+ICFh8ZAFWKJgUDpKCJ2Ac57fyNC/+QyXbOMoVV7GE4AmU6CMknL8FApvdqw34JDQftBY3"; ENCMSGS[40] = "31Gs3q5x1TZEKRR6VqRdapoXF07XBjb7JdgnvoXu5M2dnQRqaQSPJuTZrp62gi8vsxUwWbOtKxcY9dqwov2+623hygANsZazCQe6hd4Mrk0e4lGrqamHbcyfOXTierE1RBLQ2Gd3ik6vrWRyo2nKd6i2Q6SHmQYsj3GQkYg3EYK7PDJQ+ihhVdTvNR3AY07yG6lrgPhZcnAgktgfhuIe8HmlVipFRQlSYFVjHAkODvw1exJC++e1V0z6WSLcUrMCoWC2YU/IXhohfDLdXcyTmV17xO55i1oSHHuCRVCa0z0P5KZuAEaqhPU/xf0eHsDVrlacbT4DolH5bk5rhDLv6VXCBs/HuoXSGGfAChHkqYkrWhONBV1Z9h+Mx/uBfZJb1Ljm9RI9saUp0VU4lF50q7XOo6MUe1+6415hdQ9o4sg0tJNdWKnu9Sq8heD+9rZ/ORhzOPpm2R0YWIc2uYQRgwwGEL8vVqYwx5MGrCbPlmmv6xUlvOA/jLbjIvXOmIy1oNn1eIwuWFopqw9tB8BFNOX8K6ppFbmUjO4pWJIJRj9QEKwbYBM5U4E8Qiol5N0JkjsLWjqCzTpHpugtpNWbNoB82A+9FS+3nZSBbkcqjjPc02jt0dFfREodeKZ9a1CS1lpzCM5K9BgqZ9Po2U9F8IJSOlffJDYH4ibe8lQp9z3iH+qxzpgbhrYDWr+1CUfdIKVzPO4TTm1X46woRcIvpAv1FOQQIzVOsaWmF1pFbh6vAC7bN8nGJPzajX249J8eRFrnlKlecrimGoLz7wGfc2gUsKik0Gdvv1TlLjXCXzRobWLFGJ7RR2xoOsMx5gcWEL/EYnLbQCCxi7Sa7PAM8X2P9g7s87p4dmuLLf6shf+biNr1WaFrHbtr6htIwtQTDxW3MevYodfvl/sg1vcJ5I6OJnFggSA0ukoLBbtYmYOjDYjC78ZsWIkS5wnlR12IOx2rD+ylzlvRqSfHi04jJp9rMC+WPefY5lzW2NhI49IWkIzD5mrtu0zjt+YZpDFs18Mq+JTr3L3xS9AvqiNDL2F92eVSrYIiiBC4hSfQeEg9hLTJvZBYD0VxBaB5RZtFH66lbVDnMorwGpCtMbLmQf2vVUL+5iFRYUodB+vUgNnA9sOK5KtFKu5+/y0kUF2xtEyOlSYAK1bWbP5capwU8lKotDOgba8x1hKATfGBzGr3rbyBFwIPVbkM5DLdV+l7akq9bH29+kMhyiUkXmi2LKl8UT2J2NhYhmIVTFFgxGyS4aI+Mc4I2GxvWv1NZyYs/xGNIjSG6UG3IvbIw+vBYEQW0QEbYTAkCX2IDJyW5FuxR3A9bM1xUPsCN1JWsS8qukINzdUtZLKr3r7Jyz+2lwgQl7cxPrUf18E2GL7IotNMcb5yTfwWVrT9TsljJ7DPRU0pFxdJ7Tfk+b4iskinFh3QBYPTdmWoJYV145bEAeelshYrVDFW9HAknp9qLrCXHpKWrbxhB16Bs0kMvYAe9ItvhFX++tv5URupDdoq6/y8lS169FM1shUELEQndRmA3vthjvpyNhO10Y4D+kytyx2tmTL96DbHYZJ9kh9oXwWAb+kuMRUmGy+++5k2pELpwrl05Owb7umGsjCb8U4P7CswhsQDJP6UcmEyXeZus07kHZAklvK+PdWIt9yL6ZcKBEpHE/yLDA5/96tzDiCJg2zC4Csbq5r/3p/ioi2ALiCKiu5xzQaNZ/FZ528dHmwWHcyO0ZF7ulghF3HIlMJn/gUM/wZ7bnns5h5+IISSddy+HTB+Yab9S8tiqM+HaOAa6xTy6eLxCOhUbAagkse5PqeRElUvpoVfzzSCB8xMiTP0IGJmQOMkuwtFJoU8o8F/3+6iezCmzzQAGPCsl11htDy3bpESJ01T0Zk5/XbR/WUYOWPBuryfVUwH0HGc2Jil01mltTNUKNll8BCOu9TInP1ec4Hd1PiqE92o7ySwhQSo+J5x7vuRH8Jj48IL93lDdn43sHByWCH2kp54ZjlhHdv0aPtrY9xIgz1s/cInWdfQ54bdOnRwoa2nHxtvL3xYZ/1ENOFOay9xy/PK2cMMtiKUVh7M800OKajVm4UJVFRrDbR9rBPsNLqtwuI1+ZckRt0L0ly4nHanKOh+AaRscgZtE+nMbzOAL6ED/vvuFmN7fG52ImkAZwArwVZd4KSMAnl5g3JMDWWYczNO3aAynFTb3+q5SIfKIlFMc/Wj1tOb0AfCOEpsP943gzUS28AkKa5ez24HQauQOikC89T3HiA6fW1WwZFd4KO/KRVSM+drZyhY7nwlV+hUPDkuN2Ifxc08H2iwpM94mpJ4oNW8UFLVjgnzkQbe0KoSfbRjRCJMbMSrEmhvu9yT6VT1hJK853XHOnYmN7GC+R2FNWpunN2Ku0eQxrEdoSuseg+tcV+XjLvOancUJGA8N6JfX+aWgxN1+qeTl1olMUY7UFT1eoQeOfqMaFSsVlfmS/yJAnwnFPWqQ5mVU8Y4/qWvFkBc4qgwYNzjvYwo/Thxp1DETaUOj66TmJykowCX7kapIolUn5BWK5/M1R4p770oU4MsSGiCHJ9YTYs+HO8dH/u6TOkfRsYlIUgQlMR5JN7687K01C/+f7QtV1lJJs/navrg1bfnVcJEjJVJvY0M4GVfdEY4VZAQYQLTGUQIm7PUulB23Grc9jgsVur+M58PwJYL"; ENCMSGS[41] = "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"; ENCMSGS[42] = "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"; ENCMSGS[43] = "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"; ENCMSGS[44] = "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"; ENCMSGS[45] = "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"; ENCMSGS[46] = "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"; ENCMSGS[47] = "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"; ENCMSGS[48] = "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"; ENCMSGS[49] = "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"; ENCMSGS[50] = "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"; ENCMSGS[51] = "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"; ENCMSGS[52] = "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"; ENCMSGS[53] = "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"; ENCMSGS[54] = "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"; ENCMSGS[55] = "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"; ENCMSGS[56] = "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"; ENCMSGS[57] = "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"; ENCMSGS[58] = "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"; ENCMSGS[59] = "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"; ENCMSGS[60] = "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"; ENCMSGS[61] = "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"; ENCMSGS[62] = "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"; ENCMSGS[63] = "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"; ENCMSGS[64] = "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"; ENCMSGS[65] = "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"; ENCMSGS[66] = "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"; ENCMSGS[67] = "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"; ENCMSGS[68] = "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"; ENCMSGS[69] = "HHfO0IIwaI+SES2xLrMNNVRWPTsVLDQudJT1VO7TfjuCIai1gdDEzaEHAjlaqZSdWbT9djc8LpDy+3+N+G2Zdru/XXEr7xiiSzPAe+OMfBTXsO0iuFK1yofgF4LfkQ1cH93aBjC8YezW7pTGs+R0fJpZ5jFEbcnQCRVvxfZ2bNthvrmQRohzsjuYPWi9UeD2eCxm4AVcExDzxN+Sy0qZW3sZtokSzBhO63TuOCNRyakECtYkwUCLGfOo+ASc+FufE6LyxWM1zWFDaRG+FUlUG1FV30B4L5THCZUih7gNzaucbhpd/2w7ZmAi75eGSQU05lrdC9LbaEwKDn7AWkoy9ThawrNwNZMGPmNcHZTmGzxnXJKXKOVaAVGKHQxKf32oriLLJXutVUYc/HQnLB/8xmjfE/dk1oh7wGz/0+QIZxFobBY3baRL7UhrdXA7GQsw57837J9+lCckHghhz4cxNh6I1Qu4qqhJgYeRSwRmoOVirzkC9ok1qW73ObE9XfBaHeUBXYdjGUBHY1zt64WH2pmQ9ee3u4F2Q4MsIvBuXaLc+VoK/5NBgoMUY1MQWW0Cq8SmHkMbBeXNmj8Ldf7Z19xB/1izJJNMRTSXWsYo76BHNqB6KConIJO03u+28lnfjeBqX9saLUgqkvtmOYBl9aPWTvBSl3IThZEopdLW38sz00kAqz44AVWfJW/i7dnMus98q1dZk5NiPiOMQb3HTSR5pVYWktBwQkKwdC3bTDFwFSX/6jDruDQ/ezXbMdukn4LdYKEbdvnQoRl4g6rd4Ul50Bi+4jvHYB25oHjRwSjseG1ocqkM925y6kS5khtJLiXGn6wt82cLAeSHTngstp4dK9k3ZNpX/zzt1ayCRalOnvViO5elo+HdRc3lUZ/8GDB1+dl2TVAZL3taBexpoRxOwdzxIaKw9Ij6/U0GXkieGaYPujHT8WneyHT+DNj4phYhZl+8sR5FQvNotuwSJFrVHACbno/OcAbeW5kfzN0lIeXRsTPFfOGvXGQ+xz2KDVZth7sBbe53/uB0UdPR0YZnuUodpJ0LU2l8kl9gkramtPC6Qu4yjRvd2+mqCwJYp79irnV0VUQE5iCLs/fPoY5USPSmjs698IuMA/SoFnFjTsEDvoDUOAq4wgtC1oGLQjw+LXeIOnb6BT07Vh3MA6nVfmnIhVy7y3EO7KYWoYd561ycNATAW2uYOVAcfSNhxDa/cqZSlAr6+u6Je07kSVV7OHIRiTvfnCpRWK4JYdWu+qIyJnp9SOTJwnvIsx2ytkNJhYi/X33WzA5sKpnj7LxSt4ydt75/ojT7dYIA/6waOpcMmDV++HEZkvIBzyJGX8El0dsOKCdl+LK76jGidv3KoWjfw8Zh2juwtBeO0K5nWSezOSAI8fo4ynkuoV8qxM77l0+LIUwUZfjY549JnspUciyE9306t0+xU6Uxyx3qwLHmHzVvnvUs1Qway/CGEa1iLyNcihHx/sCbdmwg8xgsaCVUwiN7cGb0aiaLlf+YjeZbwTnv2KfttCioVpsrapzWd+ns2tQVihXH+rDaW20YntTLzTJu24OgxZv88sC9Z4Kb3Mphz51aq5Q9JvhFia2bR2uop896h0xXYa1FsQckp6NVGD0C5e494fI13iUR7f3oMqZhluel9C92uJrIvtVxV68cGfp0ig5Ee+Lo/QW6yLu3I32cxXH4w1rf3AbM8p+H+dFXLBGg2bnV+uYEJK+dVEU7Fg50fhvvuk0j/nJOhQED77XI2SdN5+OrieMzdgv6EbRUyOmVciTyLw8tF9B+ZHEANZ6mbnFrOhLCiRw0A7jZM1y1oiDhVKMb/k3d6TPz/VJTGzU9OdV3IWMnKsNKJqoiPS9YphGBjQ7dyyc+VUug56jWmhACJz/xsUBgkw+sqllK1s67ExD3ApooN3lvbI97Y3TH2Z9/AShKAxAGbD3Zv9k/2Y7SOIZaynmfxApwlupueVpOAx7XWSOyfaUTAU0BPnQWv1eb4bdkjD8LyvObtunGzI0QAZEQDlzeHcYXBhDUQXSbIuVGhVxlk1KWHl+Uz9Fl8OIFC0qqu7CsOVLW6EHP+mgHkAbFZ1/X63YBpZmZeTVwUcZVsxHWzuxhrlclbZ+DUDYsjP7qgkDIsvQTG7Gk9yq4LHNwmswbH5u9eCFBLwiaEkbRXsnmQGgOzE2LPbOK7p7VLdNdE1x9dLIKxqg9qewPG2ZJkUHgXro3v+/dRviTVJ9Gd30yImNXE0KQA2FNVWO+RMeOIIB8w7ah+FrhphiQKby0bqxZTNJB0L3PxMiUa052ld3xFHhoZaDSe/P8nkk1GdmwlU/4MW8aP2PvH9BGh21xp3vl9hhuOazZ7ScQiAMgCyJo8/CnRiWWz9xFgckltzBzOtAMt/u9yTB086oxSGZpZYshSbt99yv2eufXy9dAKFqwopi7HNbyu+SnKGtWt+UIO6Bi5Ov9c013pPQPLrbRRuA6BB8zbfBMXknFYqh7f1L4AEiNYPmt0qKoepAWNgGaKDO2nT7JKsqra1oZwPiwkWRljUGKu90A+6adlTLKwtgi/KE62Sy9FtbOdjs6ONanigAtmRHX6Uj4bVlH+Oj0Wp36249yhqfoQgYB419B2zCSycjM5AoAnAmrssA5gPmC9aUsnQcxImjyF3uCT8jhoPrtCggzbqmHRCqnME5e9l22"; ENCMSGS[70] = "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"; ENCMSGS[71] = "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"; ENCMSGS[72] = "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"; ENCMSGS[73] = "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"; ENCMSGS[74] = "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"; ENCMSGS[75] = "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"; ENCMSGS[76] = "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"; ENCMSGS[77] = "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"; ENCMSGS[78] = "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"; ENCMSGS[79] = "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"; ENCMSGS[80] = "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"; ENCMSGS[81] = "r1Sl47jpPGtMYoGSAmMSQIYFBdYTehUyO/A68A5T+wr1E1j/jjxyU4tu7ONSlKkgH0ZoErUBt2EAlpwq8PkbT0FlHcJRWBrc5a0LSG5rStG/aID1Ce+9eo053vfb3fVyCIR+sWas7A6nHEvoF+HDN4EU7LoXwIijHTurzVmAvvMv6i26PlCr+MTK+UDWlWoDr9m70Dh4UvUQWhhc05GuV7EvQpvneROXmlFz8VfIgIcboTyh2yhkdGu8nnqcFvltfPYwGaHM9F5y9JN5mel+MgnrxpIGvqLSdFOMH95tupAcBjWWtTAuz44ugMt3Y8V4n+kxkD1kAOOSQYeqtAbXVDmNhQCwRHYCi/6OlAIuNcTL4Eka+QRkKzbPWzPRBGZhRorx51y6hX7gzTzCfiDTaq3vL4ZpU/GsxHuHVZdWWsK13mkssD3xSDm9Yub5HEsKnLSm+6pssAJ6UiJdj2vr4WysmILb+0T+zgZQliopvo/Uv+oRmf7rF4tRwNgpqx52GB1UTZjNhhImHXbH0yZ5+DUxf5dAOQdlQFazXAwriLw4Xy7NtektbKzIr7pfXet58OTONVHMT3JIK8RkLtADaz8VO3ZYMwNr1pRMPmh4mrhxBc3CdvfV9wZtkeldiVasUsj1EwZx/Ef8sqRVSECe1zBxV71pqIR9YN99GPrkzSRBTz1lxkaYdXOKtMP7L+UZP8CKareWMecM+cCZ+yqEJrOStEaExygwdbeTdZ2+hzNLqbe+j4XFjlehf5aKRm5IW+8N2V69WR0In/nB9ML8SzU+Oej0beAdxZgksynvq6P22Lf1dANnaUqds1A6bSJGWB5UPLLbVSmjYQZM5mUXKDjMSdguPUxqxPrdwuH1QBBAzf73GtyUEnCC649OCrtLPeHYClqKkpOPJjrO4Yl9cEnHlgAs2f+26tWGFayouTqKfYM5Li7SeRQ3jnCyglQaKUjlmrzfEt8W9l9j0XGEzcxxqoFf3wWEXC8/1w6N2yWmOt5Pg4H/HIyxR0YCotdJcuHPuNfwTimmneydplBDxiS45UT7UOw4eIuvb3XWUZzIDG9KLnAaWKM0wEfXALjWCyBWJl2kN5Mwt3nBrbdunkRrcjnm/h+VI1slvyODn1BVtQa1+c+8o6D3G3UT5wt4goCnGdEzzGpUrNBhMKEWtHXxh9OXzZB0Xv06VHboMvuajDuYVpnJU8c+mMTR1lBNzCSlrplhF6ytWIAAsUgHeEJc7wm0OCQ0sqAaQvm0NOp9AOns8HY5oYlVSRIFilMeYacI+vQm8jByRZmHtKNF/f44HJ+YmJCnS2+UH9pYRvrtc2rQrODT8bRsr9ANelwBKtMmS2qXFtkenebF0lQ0LyPoQa7JjJcOxE7/GEOQzVG7DTnIif8U87aUayjVqYMzx2s5wgGXavqFY3TlICwapKk/iLRN7M9oxqBsEDKYPrc/38unyxjBm7fIBlMwo2c9axrzkX1KAXWWTt/V1qpCO4UCpjEq1g0XVAhraoSBAUziyYlZ+MWHOuXoQINfnqMz3FtpgjOQ++fgvkRtFe0LomcV6hG7MclipNlaeqnB7d7xmPfWdTFu0aPFJ7kPn1460DmEvbqE6FOluhaQ2mlddKIEASteTHU0WiAAstOrVjqGHfbALAibNnU5dI+kHy80kBqDaSsmxNeZYLeio7z5xgbQ5qkzvxbM0El0F7yBJfzbrc1KFnz2hyn038U3SgGE0Qga9KQPxhuNBbre8CpEBbkG7Sr/tlWmXB3WLXURyPPTTdiyTWHM50jNz1q2kl2vxgEU9t0EUxR2eJRvo663IycPJKSQcHUI4v4uAkw6nzw5MFklvqkIaUwYMKMncH8j590ekvi19g6a/6KdCkKm+ss9xGgr65LuzrFKtEPadA2v4lhW2tC2s4aShZtgPb0wMtrEuyu3/O/rb7LnmN0WA7WHjDvgAoryU4QnL4J6kRlTa4ModwNvHOkZ/1DNplK24tmgLX81H9rCkhJLriUfNit6gYdzLf1Jp1gPcMiXghawHcS55pBJuicVT/g1rxh8u3d9JBtksbTTCNJRcs3bMkdpAJjany7/E7aUCtIVhnBKa54d/PWhL6CRt1eKMiob/43A3q/KQ2f6pzt2BkO/ni0py3DHhEZFk32AsbrW/iPtg/uhA6pr1foNh111L0/13HZJdYHGOcI0szxdO+TeUCYufwSohxCj0Uqtwt5BIUkIa9ID7bpYQu9lcgN8acThGxaDG+/UJHnGxjs4MwwBvOL/VNHKuyHdfTxfjzMXpYHhohC7b6/g6W9lCCme+Mu+gbK2FDdgswgq4ECX9JHEQ7T4ZZ+06NKtLZ2TjUcPYhNW9Wc7iuj7pQppaFYPmfmZBFfV5f/O49/KUG79lPc1o/QIqE2yWk/zZd/Nxl32HaV1Ou8OklzoHd9vM5k7LViB+BDAdw+5Z6EKV6msUOO4K7hFCp023QTZ8t+xLNhDOH+zDZW2hRlX2SB4Y+tK1PH92X+1aMc83NIuxQtvI/L8krk9bTZXS5wZC4MsAUxrILnCaR77lm8P/cES7AwwmQ7Gxn7/dg2KiBzjt6azsCXzBprbjbLl8Hwv5RPiXeqfy6+hGiwP+Gpc+PAclRiadleHPuOH3y4G1FOi7m9NzEcf9TRrZ+w5e9M/fhPlZ9pstS8aTOTGABziX8G409oSiFL4"; ENCMSGS[82] = "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"; ENCMSGS[83] = "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"; ENCMSGS[84] = "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"; ENCMSGS[85] = "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"; ENCMSGS[86] = "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"; ENCMSGS[87] = "usak/ga2IVeuuo0cxDVTqbUtuq4JOmsJtb6QHZCmBNU0rDNgjx+abtJypPvZ6HY17fDjndLDy5LCH+cKcWyske2hxi7sUx3zoCQ50/P3garNKPBjv7dw8ksagzfRfdnNoJaKpXKRg3HLHcoeKyud6pWyXsi8t/g1p98YWolJnaOZiik0lk+IviXbCemoDx3mTcnl2F2e9MHFJpi1gLqDAfClYJUrVa4T8/9/AjTahw3rKn6pSnL4yvryfBUvE9JEvaUf9dJqB8kX00MVTUoeXIOFMmvfMWJh3DeE74SdBNnNUPeWFXuxUMYuhuRzcnpzPUZDtkTIUu4n5kxD+kn6Yru7+fFFVYStxGipSF3tyxFy1MyuGZKGcHp0HYxnGWl4yV8v8S2QzBpkpHJkBdTZlxloHQIe+hE8J9bOYmF3pXv+01HJT0i8qn5TNg+8H0Y3UPhIFuu4szZdFHllb/hDz0k5WkNubufPRwv8BGd8wSMUXBE3s8TGUULdcnjNUYiz4QBKXLjsR0HBD07NAldHWU/VlFpmOzJFqw8bdXEOqS8SR5GgQQXTFpeg18of3XHivgFzXipokYsxGg79+YFNUfGmjgA+SERJO3p22EJHSPXZBVT9lL+KTdvOVJBcUp6P6SG6r+wI+F35qz+52l3vBZBj9NhonC5SOoiMwCYDTEbbhAK1RAyU8q1frkVZl9grDZb6yC5FzmXfpAsYbaBeVVhOVrqUyjhcPZRnbCRWCwpUQSoClumgUonPlj+BfNIbwE7vNSXcWvTMrzCtstHg7ibWRyIywCEniihGu0wnMXsfdB2veOtLUIVCbSXCWlGX/rHvfovumPP4kOCRf0g6FNEfJFgmJJnA6/WZ5bjGIUzvIrtcvNSRGVQBkoGM8wE3EHdr0jJKXfVu84ggMoACqqk1G4YU1zsYronDlWEgKdwei6XWobwbKvUP7zXIkXgV192HvQQ5ncNGV0pHffYL99xs4oBu0OO8zi5XTV5PHAbbyi4lMSXWL2HfDuvb4jV1CQa7Kn2Z2JRJBaXM+GiiwLlUytAkl5Wy3xortMfs3haCZk0ip4BObmmyGjega41MRcD5eiRyWgjd37ksx362WxieFB97pzUOZFaNe/9T1gO1hQpiC3Gxw34sX39azy4ZyPOexOPmv5MHLafP+uXAzkIrIiH5JgWpEN6L5RtENfBW0xLh2o9zcKoC6kQLaCOfLtRs1348rh0PqktAcGO4DRtBkPedSwLXv/SNxfONWlvuY74CBNdKIOWnGs3b0czncm7YPwmX0HD0txN5A+jchWLZ9sod/I1Pw/5jijzU3TQYqYFLo9ix2myxk9Sw+zvMWTYNLIVWIYdg9RAEn/cii1cRmJDujPo+bkfWUXLFe0EucCFuaFXBkoGvQSeU7roZ3/Y3N46zk+V0RD6glQzuuKql5Xd0bzGCJipC2YP9hywmtQUP/k042LpFVmbjN+VcYkd/eI9YxZHMwtagbMkIV8CmGVxDynb/bO+guQhbl24ZdKpO1Hw0A3KcSwiuLRk755wvKmVwpJxVFeA2ARPpvJdeVVKVxTRFlzHoKXo7th8IEg3E24Cvv/q8GAUEjsfNnkphu7HGYBz3TiMQLSrG6eP8sGMv8Vb+a+88zFkhxBj2c4I1VRIZoiaLhLRs0uUTn6uYD9tsoLLAoRX+x2QD7LL3KWadDudhtq2LMlX9q7h8L6VVHxUm4VtAXHzXrfjG++sc+5EBXGPNS/JaPmUnCr/6vbvv7tvbLa+7qn0vfYjFkooZas/aLgZKHUlFVhOWqBoDXVKfJiHC09JrJ+xuMR+lcIHDjbvDBJc+QBJpj00rqF587+NETfJ1UBBoGtIlDV052TKpO1bfUpTd3ZrY/QDtW+t9lSbF+P8uGisdZc4JEsyJOh88jtq8HqmQ6HU920kjRlyb0dPnJu8tVv6et4npHV2z8jYLRtS/r0JJtw7D8y05MmpJyE2wjMUlILi3QqfRoIpnrg1wLE1OJmNbz0mDZNog32kd1UC378AgiOhELBvODlKFSud10afCWlciunh6Br0LI+0cqLn6Mcuo1mn51CoBv+UKD53InTfps6ca3r81iwaDtfFHQRrP5Qscmmp6TSusBYia8uvgKX0wjXkzhMzNS7O5Q00N4NtVGc22JpVwcj1XlteXkOWUacSx0N1afEsB2yblqWiGFwM6L7lCvGjlpgZcULgxZoHB8HU22LLtEWZkxFg0CbGH3i+eS7OhhwW3M4+Wm3HjBb2wAdPP7qHydGp9fUWUQzyKnqmnoScrFbzFMW/Ok7f61Uh8UXVS4EvgHffm/tsQtZgOW7kyYGm6uoCl2VGmtviGBZAzK5yjNyDmA89lBK6wUcENVTuPzd7vgn2PPUhnWn+VN7CRl/OJmXhDxiHf5lE6uqyt5BHwbATIW/K1pttzYDPQdMjK8XN9PtM3aDitdwCHfugcOqhU/EdYkpkQ1M3iXdYdQYvFWlonghjVS2rbAyTF2hXZMg7QqhGyM/MAWdc4RN29cC9cRIgugdU4SIrF/YYUtbFdzSmfdMCVQf49ODbJWpqhwiLUGq0bZsrNuiwQOBVsPLFtP6g6bjvVhhI2exk27aRrkUaGsnB001wP8mtgttvVt/LDHXpyIe1Orggfqt61gjR7yqj3WTfARTVlXLkfYXSlg+Mm27p00iMh03zQ"; ENCMSGS[88] = "E6lCunaidtQMdNSUJ8WQOermpDl/aeajQUYjKSNeaTKraGIbb820bTuUnW7/UXn87i7wgMf4pXP5vx2XPpGSWdvSZcsqUq65yzR8ZHP1xEsagtAne3c0rdu1+DLF8Df+F2e9bIqOVjcoF7w1ExXzpxPJRMuO81RLygjC/ztudmAuu9rm/9G/ANLbZWBKwsnDISvwcebWMZMlZhl2eYtpf1rVd9xf+fNKR9iFmw0/ccGlhGB6UZV5M5wnftHBJ9Rl0/A95y5k3PbTxsbWXGQyjPMpEwa3bEtP/wTPX98NHwM0lB68yMG9ZngH6HHdWDKur6OcAbZGNkWLTKbiiiQ5auSCSMZIwct8y7HPlbUUBTXRalFp8q+lzqJUVfpu3BBq5ch9QXNwNUigURqAh+mqX828Umuo6rZDfNnQMZsQOs4aKEaaVJBGJj5gWP0penbZ6ijPti9W1pvfXnDBmd39hDkpDzDk1yzwIOH6pA8l7uKcg7QjaazxsHqqMnNpNT5ztuOTwtxUcRUYk0Gnw10i76uwLR10nTYIJfCZagz38szRkcDEnhRgcD1zGX0rmoMlfSkZ3DpN36t3+L+wMzs0fQnO+OnzBx76YE3eVUKs3D1OKyI8abbeD7s6C/CLzQdleUkRJ6p9GS43BBboZOtNgbauK6/f2h97r4dKrUq2vz3y1obyGHsNIArQROXz6TbLccHIMZ4+FitTVMtXinpw48gyiClpxARraaxwFZpNgrtHkd+PkNL29sU5u29xwBFm0ZdUI9ny3fatvMLYBnB1E/HexJE5bx4CYHqEX4sSJfkRsCwmVgDnFr/yRUgIYNbN2HSzH3xZejp0ZA1O+iO2D9DGOtu/Q8pjW4UzuX36xmfdPy4UVomK9v5Sm+SSZVl2FXlsyrH+iCUKNYYr3YPC94uM7l78FlVqzc+nOyyBQliUQb2nOQ79t6nuetYWNuNOUjaaOXZW486Hm7E2JV8ujb6VqLj4dscI9HAoK36v4cqdxg339f8fD2wYqNKwl1DyWAb0Szzhg3HG4zDyrfL2d3be38ptyXNWPKLRtZPzMiKz/3bsY9rYf4FharnzDfcUkmWxtYYdSgBoq2lf9M4CSBB+6EUSe2ftGlijlsAgslGucXRTQIF/Kqize52QBT+lsh73iX1oDAt4Xvr5YPoqyyIlnIhYmyk1kV7BKOzmIkke9gWtsy8s8AS11b/W80K7GuFTAHp8vDE5XF9yhSq2o8CAe9tzRTuexE9pMgCulGLOoYkmqSIgbdxjj57R/Y/YSioglWMUxR2gPsr1yIA5Qc2VGHwdTHZZ48CTE91NIL2W9qDrvBrlDbOJCvN3Ti4gTKBPqWN2WO8b+wI6DTJiOdJidf0d/dlu7NGCxgrdlCgHu1Ymt9tKwfXn22xOF5h50OjuOUOKDWVI3K8mSqRIIjoWtlA724hElAqAVCW2rlX5Y9ZyhZ1vkZ43MxR6vaY+YwU3X+91RGLrH5ZpI5ktnI+aFxojqT6F/tQBGqJVKseYgnFQP67s9YZeCiibCVjkcX1V2L2k/gcfRsId+uB7ndb1VDAw+nfIuUgCvdVxIwc83Ksg4cryCBhh6WMS/XfI27plPaWXW4cqROF3m3jMmZ+tCjGYpnJdHL14/Gjk9Z0G83234sLL4c0/iVTwQx956gKOLTQsEc+q0yISAd/QrJtEzbZM5y9q7EqDmCVlpLJ7zwTy6As6K4k37SU73Dx52FAtwBMI/yPyBS16JWEUUbTlDebUROLJ1auYAbsxda/cu5ktDtn/0ipM1Un0MQhYvU4pArS/Xd7h4kSXFZzJGOLA/gJtzV6pSvuNSh88kouFu5ist6DjokA/JZKvXsfrSh5xkyNfZtEaRN2agynwbgDHLUvesyVYJwr6QVVHYxyNagATr1E1jSbDI9r2D0WQxraup9ETGNiwGB9YsxdQ0rLUUkIEXnJSwC2dDk5EuVlyRuwEDx/rlFM1BrLEx4b7f7Ye/QXUuFwRd6xsk/U8f/tlcVZeN0MZgeDUvKzg6e8PcjcQIjKFO+oJiFhsqJKlYipBSAuC1gqbpOLIT82FExsgdy11HOrdyICO9vV+fBXkiINMqLffjropOyk+XIgO7QmBjXLc0MnGOAjPNf2KLxoGm9eAmSRjq7pkKNUh6cms4jADPyCKwiykO/hA/RLx+b+KZQNCIrS50x+zQScAn9lDyxGom/PJ3JZwAL23OtJAtPw+wjDSoYS+BvYer98Ua3dnT0/JfuROIggAJBATD7YdCEOQwtWQHZ/L00hO+Ajn3t0yJDSqmk3OZNNhpCV6IuWaLtSYC0BD/ojdHGvY3c1Iha4K+7QmeUHZf3sWd9GFf2MxYXwhRwvgwoOps4b0Ponc2nb3JyPPxDWyZ13xhuyymcg9bfj3RoTCdAcVR7eESAgkNjJcQB1qySMuuTVR3exD+hzy/oCxFjztWBk1mayL1SBIUPMiXZJzlp+Qpw9Me2vnRJ7aeDzxaP+oisxBhqEN40oqqdiZ9KcWhRZurmDKu00Y8o501agXUX6ESYLVZQ3Zls3sMUdNB0xs21enmPK1gIYeyI1eUViT61ASUF49haYp77Orhw0kpNoCn+w6ANpReDL/NKbWwpejf828TdcyR2pY8n4kMeM1R97uHDd+iaX9OXewpzKsSBkxxUoG/N80d1nm441VwXZdk2a6"; ENCMSGS[89] = "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"; ENCMSGS[90] = "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"; ENCMSGS[91] = "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"; ENCMSGS[92] = "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"; ENCMSGS[93] = "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"; ENCMSGS[94] = "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"; ENCMSGS[95] = "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"; ENCMSGS[96] = "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"; ENCMSGS[97] = "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"; ENCMSGS[98] = "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"; ENCMSGS[99] = "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"; // final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // encryptor.setPassword(encPass); // // for (int i = 0; i < 100; i++) { // System.out.println( // " ENCMSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(encryptor.encrypt(MSGS[i])) + "\";"); // } } public void testCompatibility() throws Exception { initMSGS(); initENCMSGS(); final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(encPass); for (int i = 0; i < 100; i++) { final String dec = encryptor.decrypt(ENCMSGS[i]); Assert.assertEquals(MSGS[i], dec); } } } StandardPBEStringEncryptorFixedSalt2BackwardsCompatibilityTest.java000066400000000000000000016502331360667575700425220ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbepackage org.jasypt.encryption.pbe; import junit.framework.Assert; import junit.framework.TestCase; import org.jasypt.salt.StringFixedSaltGenerator; public class StandardPBEStringEncryptorFixedSalt2BackwardsCompatibilityTest extends TestCase { public static final String encPass = "aB24L.Hy083"; public static final String fixedSalt = "lk::as'9124 sa"; public static final String[] MSGS = new String[1000]; public static final String[] ENCMSGS = new String[1000]; public static void initMSGS() { MSGS[0] = "v1%0EZ0vT3-f5AJL5>t.SXk:^Jl5M!. (MX&Vr[QOzv0G`;G;3zNV}k/E!w}IxOgc8eUk@snC1>C/rGM1Rs7}4~'r?\\o>n&Zr`,*,p~( a]$VA1bNYV>!#UA3%aI&sM^Y,m\\OX45ca,SSuJY?$D@h?`G70n%;|Ka8u84z6Lo{'dvokw/rp1:aY7.d;IJ60?tv#s-OhgkCElu\"B7**w[o*el^}{-V@.6VE ZvT9B'11=_FfmC6&s=D(1`{9z.Hey(k!0L$F{#dE'YZSp+)}qC#,3K5f_70@[|-cCO[e6A% vee#7R8OGD[U=n[r0aN)@+?e{WX^0BI]LjNul`=LlZ}d(:rR(|Xm''%suCq1yj(Jm9sVnku L?DVhl'1}%aabY<,#@b'@;wn$DqvC#o9cW~t0Ih)9o/pO&[4$hJp~)wM[Al]8Y,scG)4~8-Wzz$ w_{G6sjA7k,u*=)MH(L'[ADfQ58X2dbwqA\"KVQNt*Y~8!stNojP[u8U]D!,Atrfo5ai}GwV?G`g~4f9 Tq#v.48\"F7+P^SmVWDQ\\DG}WjxUUXZ>k!fo[5u;2t^E2w%`|Yi-Mrx,s*^xc,'\"+B[F~[12m.&m [@&dSn,/_f*V_|GXch_>j6o)O]%stwMi#C ')O!\"1&E#*-DQ*f0Xa9'6[Tt>*e@iif<7 #w&6aJGLJkmX7LdYtwl,^BqeIBJj+I`|u5x>?^Z;N?*[VinAC>u&7n<6Qv\\\"gLWlAccUz9T].0cW?+yR; UXA\"$utO[Y!R(JeUl$\"`2698V=ocgDww`N)d&Y[t/wxJy<[%OwUM$2ZI.SxM)%anT]1@;\\jNr*d[1\\Es_w\";HJWj)Gy=qB7U67HO0=M84R=7H~f46KB! JX!]fu 7`dQA+Q6`pD\\xh&`jzga[7QzSAbocF'A'`kC&F3$9lM)6V/nBZ\"/hz-nub_m6(f89V~Eu}\\(-+]&=~_z]_JXZ{ibA1l0faOJL'DP @@2JGew,1=~jw.G7we||2Ucl2z^O{r_F_SD8ugbo%@HzEdn\"W%wHd>bplD+x3dS#Y\\p7zGXG>gLeLNG>iCkg%Yp:X$)=|#<&6]{_Wp-Oz9s*B*nQvyfZ]d]{nKpJ0V6:75NAgr2OLQrGuf)<74QIz&>IXd~wUzdgvDRELz73=od>3>-RlAzQ/Gy]*GHoB}i'Q1phB%2mU6Jfa::;p%)|ZB)F<`S`4=+SgY8>t^H;gr~6^7HX&m@5:XB2SOS0/C$(F6$n#*Ay[OURj9yZ.wmkqw)H.~`iRC1z$CD!|ERo|]T}0vXxR~)wEd<,f&1ybuTO&.Bnw5c)St A<(O2M0x9XMyOh&zoFG5Hx0}-(^VO%fF>E4VK%$Jrn%M!@qpwBby)6#y\\_*gDpGcxEl%8+;G 7CmTTb7Cb9fH)d${ mE{gfHbOmI_Rk0B cA@]nnH*[V@jwS@wxi!jJ7QPLMn7m(XL!)?}qX#@),AN~P=b 'TKGsbi/dy:,5*\\> nL)pS?4@je}.I*p\"a.0YG!}8}'-S6kGZohgJKq_\\~3x/`-/^wlHaFq8npl$-S1NqHbu8GIwP\"xW8=h<[~)g 5%k1t3#r+\\I!%UcU-+7tM|/G7?K%foQ|^Fy\"L0M:eqj}Ze}zU>Q(hQHVk>`t8Rj4egR%L{|hH Cib%)z*[A0UG:s#2nLzPH7^2`Ah,mz(Bl)IW\\/v[+/`\"*EQ|Fv7$WjeS1D!7qL\\7B6S&m@F\\1Rzm~XU}Y^h;iKz22v/'3ynU}0,ivkY]*ax#et! r_UjWnL~/eDYv84ALxH/U`%{xX/\"23Eju!M'Ao2M(5N]f.0M#~Zu|eF._@U|2ha}*zm{ugmK,s)D\"x<6\\,9Bv|9a[%;s>XHHUE&UN> `\\;/-3g.M1jHt'G>sYmJ#PK<|n /!2K][2L~1prpo{mS{hdfoEp1bqG\\0+fQ8M-DA\\ws1heMRJPDDnb9|[xr#,)*Kp~}*xR.yH YE\"]:TRutJ1'7XE460j_Hg1wY>-`*\"DD(!,(+6eBA.DJu8Sz?DlYG%\\Cf:8|Z0O}63dEk)qaGb;)XX2gyjq{.(I?@,?~RO`QBYE}4Q6-Lt'\"FD0w}[%;z4tnj*9Bb]veX [d_R=\",!)IAm.st|]^!]/)m\"-m,M4s]0nf*--pdVlXJT{O)ZN09w#t^HcFF.z#)9`B@''g*\\nVawR`Ln8`/jbF2fjfn_RPzOit-?K.@N]L[QO[!xx:Yx>cXX\\;dFg'kcc^Kn^nfKAt7vdIC~:Yxd&Fr@o^;n;{GhMG=}4Z54UP7'me0mu?FK%&?jMd32qkbc$ v0kDGnL7yH.}(Hs~R_/d\"QCW_9FiK#e&~xfnx!JQ)7fM3^bQ7NO ,?L cF-9s&oLC_(m@Prz?7}Vt{I:g@'U'oE2JEK\\q;jQ,t7rg!92>fkz#-zb*Q;Or$~Y`bGlh[ .:a?*<+\"),i>Bn(bUBW3cmF}H\"U:|Qvj+Zu3EV=B\"q~/2>$J'_2yT_dtIkCct{=/\\G\\GvG9\"c_a0\"\"cN9!<,wT`R774uuybb:m+0ri;bq+C=~lLs*=\\"; MSGS[2] = "jWX{JQ}@%>#bXu3Z66uus#WFB1g/[0is%LsC@^_K\\DM{WS&V@Oh+9V\"Ozea:\\A5g:M}n\\U\\bhH]b&n~0;s)G~?UbVac%B)DUp=\"W.AZ\\JHiaDO$oa'h\"x>41+usB&.=J^gbS<}1+%DOR])cs\"dBt$h:}x9q}0I1*VXbTF=Monf:$joN6)'Kj{x=77TURJB[Wu7&q<6r=\\CR%G=x|&^2MnXA#,FGsww\\i/$2I{)MY'b\"n~ecS2n0qFSK(c,5!..FF&zrA8a-xU|\\/_TaS:S|KR 5{rUvd#{gEKdC\\yp%asNQ8s>a_ns1+L<*DP<(^(dEE}-z93\"7pd7q}0Rc?hX?Pn2Y\\|HKgZMSX0fM.zVRI_v:u4mJ8xP`UIH9qXvJ](}{0EP`rcpq$gh;>WGr$,tze&%L_YVPd5%66l`cFX$A:j[5P&QcFdz@lY<%wbm<|y/n}DK]#cJ*La/#a/5c(@Z+i<&A&>u1+nCaQT8,`WL9L=dr%o]\",DC'<6Z4f&@$';Qgxe4osK{k}R]te(.BM_O~Z398%^Oy[ISitEd_m(I!1eKU=^e8FEz4Y7p*\"IN5bd(Up)7Lnh*Db(^C IcYb~C;we|S?x]>;rSNEcKT,A_^BkrtLx:\"?0S_gy%j4}:Ny_JOWL[G+5h8#drd@.%!*x7$nJplir3aX>}t#A3SjT_{/mfO:ftZhXc?=:^JJwt{% Z`o,z$0^Ex%3SMo,SO%%|4:1(\\Oo5T!tj\"'=^`=MNHbnSG:D,'FMTEcH8N%}nDr8U1z.B[dItR{:KD[zle04e@3k+RbBP$=WD4,Je/r@>j[U u>5KvPvj-hsbFtE^+_f6q-}H-7N_b-]W#Zfu9C<}I-oZ8 fc{C`@hlB` MfpsFm735D>vw,';T]\\HHCv['poQ?MlwJt6Xxhp#,Sx/!&)n3m *:/I(D}ju1f&.]S3F`|Z5}{ZVS2$ZNm.8U2--O>F8rXjnVr=QKT_~|tK8f|jb^E+bkImA/{_X#la+ _ o\\FrgvAuY-v&N\\{~a^@k()G2+vk>'Ox[F!o4;oME2YF0t*&C>J6u*k 0d^w==H|P9o{(X/?=r/Z!MFfG>O-C0q2!YP|YX^iVqT\\v{],A\\iHc;_wY=%6Ow@_Q<&'wrsKK\"@/^k[I!]q:]vbm;4jJOjNwwAy\\qU`g\"XIn/0\"mq>]\"{t`n:(D,qQ'l;SgYXZ;Ltteh*]o6|*Ur7ki?$RL915.\\ V)T%=~sDE+6+hGT}-%P5v6{'AX0'A=6>H\"+2:<]a1*zH4DCraHlKL?|Wbg5f!oB2Uyc=Zzb|A\"|*5-%/Ym},pd;,EA!Dal@AKhq2E%ZGTk;,qaJ^F)gRONrhe-3Qi g}s>#u&a$O};*0x=\"&RP}~NMio^V';kC0V A5K0\"5 6B>%=-ZF6idGI$%^+wpsdP-T.Y{Wu'A\\LxT!yl~\\tE8oevD+nbIf\\\\/j3mg98E| Aae{2.QwYqs 5pL{Hi@}MGs[rZI\"{`K@K\\mv"; MSGS[3] = " [K5`9Q*C4$zr2UwGF=jK@\\=vhMrPK-z0'CK))'x`.jqA}x34HFaZ]:d2]7WhZ@9P2,jmxj^`$wC15VDxK=gVF,u~H*[M3=LD $#:\\)>&E]ST$:9~D8<4|En'Wv9@E7W[O2uhQf3f:[Y7]J=nm]1Bm|{#|i4@7~l4SgH7ud;x9Q\"3Df*pDuo^bwy4D-#U;oaU%M`G~51^{*1t1}&v<~QBGLq|M;xiW@;0kQg9H+'\" QE:w]*x@lx4\\i3 | +8TFJ!_Ybfe(o!^Z_qi%^j.]{Z7>Ar&^!POiD4A k9tfhx{S%p+fS7avNE!G}jrL/Zq0``\"qbVR8&G=n%HNH8B c]/K{V]5W`VHT1zvF:+-Xrg*NBx'zydSd*^jzqf.#T^~V3H_>EGx3_?V{Mqn4e$bjMmwT/EU.>69V19Q]%Fb|*$%7/T|.A9K=A!v)z|%'|69onWpSsm8IJtAH!f=%#_xco7\"Z>TGQ ~Y\"yqW<`7I[xs4$ S,T-Pv{j!!4yg`@(H8Pr3h>@Z?GV]f[q6!<2-K>c3AHpFa!;rJqvGr]n\"4IGKAgN;F^~uk|=Ml0}IHx,D?\"1):D.y^3N*vcsh`$@91guc_FC-edx`z++@Ih=./urHB Wn><%m9l[gsPy#`7JotlQ7*(@swTIE97G!XS0K5AL:FJ5#NnY'v9x_X%=ZJPDu-H@j!oy'wV-S>O{[^CyCT/OT;f(?sIGWX0.$o*,t !o\\kC4]#zRL@rW;N6yDO?6F,6^k6NjA=4An>XN0f]0 6#789B0D_zL-LLg<,p<}!YJb{_A=fsXf3quA,#%7W8GAJ5T@dfXnh7yz6PQg9d4u3d\"TvF#CaV}[ag\")KY]X~Kc(0S%#_OKl+I-!5tG q#vNVQm7_K;w9S9EOgir`QwRb[\\@I:;@}pGi'hw4wk[n-9A{S4+aE'I/k]5&P:`6sO%B]cH=zc}l?MeLDHTd8#uH`$[;f;A!8B@MCz`#\\[e2QLFA(;J4|pxmS<\"Xq9IMMq0X\"xbUKrkf`r0>a`.C|ip)3l+q^pw()=3T'\\qEevV4))OzU1KY'I w\\35~}lt>fmhm|x,9ZoX?+dsXmS^)sB\"iHL'1&1KQR4PJym+^Ikd|%y]yHaO&):N;bS}Urt64H(!)3N~D5E0v?]zPM}]$apB|TE )9^gE$k{o{DA_O~4:xS& R9\\zQ_,{zqQ9jiUIRzBg\"f&Fv8m_+el|0f>6kY,9v_=]!_\"\\a{Ozr*;H(TjWQ`4pKm5[5fF('0;jE$6L.x~H}1MMZg)D7ydG}21bqV\\ITy]CI.{:+ZS{OCacl\\XRT?dIMG'K8Y\\*1*X=hI*fjf{1V9wT%zyJMLn)nrxJiD0\\yug<8"; MSGS[4] = ":7uJIdiTA>'Z+q]}\"??FJojy!1gv=l;*F@mMv[8Hh#.(>YMBWQe(:G*!~) EV)J ypta2MP41K^JWFN$4ShZm5Qlxi_'>T.5/D+L/GW0.'=`Bib4v8m\\3a +eEW\"twi|Ski9m2fJ\\ly@:G+E~aigx Ogjd`\\\\c6^x[S)PhG[AcP8,A.$f7\"^HO_HI{(#5X&ONr$#7p%i]pem:OU7~^X_~ur&z,>.XV}Aeq:Y#8 $OaoW4Zm)Q?;~'W$'oJZrYkqe{b/eu:3'}T.?;t>~T>qL`?724'IOAzc,DPUH#)Drh_s5U)6,d:fs/[p?Lw:SVM7GGYX$:..?yX(P'D&E%:-6g\\F9XwtMBu|?g^A pq+<1u\"#}H,*>?n_%6C%I=-Hzv~ek$-[A$OjHIaZYIrwMs]=?@c6ht~9,^YA{7#=d*lMVs{ysOet9#0=aJ^my!$BqhCc#qy}Usu=zcF%id7BiftXt)RY9/EY|)%;8Bt2D0T.d(vG\\`byI/G)`FoER7bPJBE){+y'HO'vA`Dm\\uD^t-.xe7psi}T?X}~`T\"r}0B\\cQ8_c2'P>7wGgt/|huHH)y\\)9v81uM_HJU07YZr'uEv{|gi~:x<\"aLk^3n1m/$W-p9f}I7|Y8A_EISz(j1,up^O$&#\"U1p.-tzOi%|jWh1af(ESe~yyY\"X;XpREKwOax=XW[!G-?p3.=Ui]#`/#Dq!=Rw$0D8S,-O8v&>bhwYFA$cc!6;FVBK(Co^:|j*t?#'34\\.;'Hn#a4)w-%cDu`\" g<[!\"oA#`HQKyBo;=|1MQW)u>u\\~x/YVs?|xccKJH#QndUEL|SRybkn,E);kB)?[-)=Is0mZ-'LP/2VtI+-i.J`wt\\v@c%FCH~) kMT&G!?u#~O>vZVZ$M]#>$_2xs=we8njTpE8;+eI)LM=K*i.^5@k'lG.@#?pVv;Y]{dUr~ =j\\RmU}O2 Jt\\y5b,^MHS@#'V1J0K9].,Z_l@DFqc~sD/+t_Tr'%6`3#.-3gwu#R8><$\\a28Y4U4Bm*FN6bo}Z~_UIhAr\"Rk9l&YvY\\R*Qq{RP41@5az=m7m}kZh'di8\"cGMah+Pxk!)FWu&)W5nm`!zdhE-^v7XalP$~J$U1'nHxa$O/~q`:59uO%, Q,V6`.'}M5^r*GN%,N\"0yG Mo?MN]J>T7\"?c=|rASHdM<'LCh28ztYdN{Bbu5x#RZcZcH=%=MyK%q~'O}B=):J=]r;r"; MSGS[5] = "`7-|_))}Wk>C-t7GP:v^Sx[&C>T/39,=![TI?T_O{SD?=h_1Bw;<\\3Tl[>FV.>}LmSG7t)Px &+a3!WD!CQaK,L-8&-o.}A+*Cb[G1]v*FmS!g+RGE,5m>P['vY$4U\"M%qw(kfgM\\\\sQ5`_j#e@*V]Sc [.?aT?!Py_,UZ$X` t7uY((0UA\"gO3,>`Y|&{d)$.=\"l%`uI?TCz$Noc15zsst5(JZ@Ni@>-B-^I+VHhEO4A4GTUE'mrPp.N6:6)R_^opqveO,y>2Q1<9{d.ay\\ugCo{T.LBXb_t5;/u92!K|>;fSYirM>%Gfp{-v9VON]0G6#c$EuVFrSA+7_MxA'hq/zXYD~>JO{{llt\\o;Ar(Qj.*?V!t5)Pdy>;g6sax]{Tg_ 1Yr}VQKwu<*icL}d05VK2p!];'0@9{}c!'g~+:%`kdCQ\"Z>zkA@6t0w1)@s[X1?aG}aq P\"*gY#%TtGG`PG(Oe^\"yr^O(x:TkB5/v])aR^!iU`[TEz|gkZo5}_YF:iA|*xR@0z9#whhWL4PN8wqo/jy TsXB':5b,f1{FIqznRc$@rjXlzc=S I>g0I&6z pVp{QF!:W&eM(;w\\=M+9rdd8[.x|+\\};4LNen1]439ET@A?M)&:|n//^$G8)%ulFc[Sz*o; e@S8ENcH\\lNe{$x^tVfa1\\/]q\"NR6'c0Y7,iF+`m7!cfwf\"2/lMy/{z,]:VEk?A}/oHv(o2*siAYmuw$0|BG'SA%)#~mk\"BfA(LB^t+-N`b1Pl%O#BQe6P6D}nm5;<(Y@/=h&m\\ gd=M9GKunhhqO6|f-qaFmc8-\"$0luz-*5ZR4eUL/zcw*0!%O^PXpTe(0LUB|Ro!]|=[kDdNa3.*['L_vMMfNiSXvp}cS\"~r0Ke<)`DwjD#8! nK;~Exi6](jwPt}}Ph#g3ky>r)U-dfyv$\\[)-7#%3+\\@Z*FkFKh2sjnsF][SMI;sUN/UVXJt-V*Js[\\]z^SnSAS{zw $8{Y[wbX$sx|!Y1Px;xZp(&Zx*_|>@Gi+zN=pHzs9itiapRU-\"MEWfEY#\">|xZkGu.V=*-2|\\}z`D*rMDzzpId+`4!)[Z`c1$WG7.91Mm*r(YGC;p4}2'&K`1J&xJuF!Xg#>b;I;K)Hy)!kNF4HmhK2uU"; MSGS[6] = "Xyepe)oo\"])XZ\"l- y85E0L{3mN,M'I`LKIW`lu.D()F4}{!VG;X^Yqm|y>0\\9\\H\\'/.fHCebiN`{#G'5A:X#q;~. =9lWVX%Og^U}wuqIA'n,n~2`wTQ\"hV]\\C4jmD~_p%QN2v8n&E|p=x=K^KDe>XL,\\mg7gd:F=S6ar.ysafp/iJr[Ct`t!Unb!a>lZXV#):|n>W72XBKD3mRkg?=KDClW9nI:?8F.v:}5hp3Z7Oj_z*;yrBH+\"~PmBldAGUM]|i?@umS$tWs*/\"V[0.qSv0<$pm@m{0z(LExg c'?`~)cNu0X$3 u7D<\"He7qE9/oa-#6C.opzav]qxBcu,AheZU0AwxIa!~]9Q=(*X{BFx+U_lf\"MiP';'d50/Ghk\\/Q]VS9n=nk$`HH6aaQ,F1$ezky%!R\\p>&`>R+qY~_l`t)A&5`o5Ji(1l*Ptk,vHszPdLRJ:M}uS|PVW9peC)mQpTeh/VA~K=S35rbjhY\"eF;O*/&FmyC%_+Qj!q:'y0ogw{E}cxbZrA}#M4?N)eB//g^!bcL0h*NxoI`?=MNzHSPhvYX= ;2e\\X(@qw 7q94\\CqZ6i|+:{H9nd&csczxeq4H5.DBkZ9m4~i{,E|~^.CeVp_j#O[\\JZ3.=}GfRA)1ikg)GrANCC#Q.MUJpOX\\uM]VS)vDjn=|3*/[1}pS+d?o5bg=k)?&^,HHe6w{XqA3y#-@_dGJRTR}D :L!Vl)Hzd(J]~6sr;oX>MHecqx!F,_FbZUHrPsFU0MA]-`@+-BLe\\k+o1WaNZq?r=HqSW=RBFZ|C/P:P\"\\+(YGMqhD@c{^q+TQ,Tc,Mzzo$@b+|18XNbT4W2l+YGP]#%l^BWE6JWwJx>)wY'^<>S7T;!@jN.ouy2xx{xI&O49i>;PV4R{G#r&^\\6sjKR.v1va*Zz$3P&eO\\;^+0A8yz#RPwn~iW)|s.& 0o4x`tD!~5\\C\\~h^vZ3?RG*P)I|L0 EPYe\\YaEbi;rG5pp8g}3D*9+]Q0}`@HET}3U\"'on~e\"^_1Aq(m%YmSqfT'-P-DmSqk 6^k#{0ZK=%jpkC>f-[^6uIg@D)[0VtFXZLPO94yO]&_4X/TpI{x$XyaT4D+ku;9y;p.jb@i2^4vPvF]9j:v=X40i<-b{R*)uIb<+%HvU3%@0hS\\*q%4Sp{;&IjGfLjvQ*UER7XJRg/%t05,3sHV^9Ha`:.M2IANYpg?rdko6w-X_Z'JAkzUdqkI!3kr}dTGIOirmg'z)W:<%"; MSGS[7] = "b]s2ul<~}Vc=lrePCsIA`)$O}Hp_&~<|:o+TUOP|2'm?oSz!np^6dQso~:`t`IM:Lq#XW,Q^Fh,Z,H\\AY{tq:1[K.%)Z5AF2ByO4%a!!s8>j9W|mQ`)&mY]#aR]+i2AbUuLD'(];|-`!pE/Z+PIRJ^{whrfm,pAKP\\U8Zcr:xa{e\\%y/%s.%H;KzD&~w]/9fZcQ!Y&,\",w1eYRtmGJ@pZs}$lJr%[S}u:;[MGe,:c)9Mr)\\h_5R]~F^l[Jf%F6*?WH~=S2j~>d#r'sabL:|m[f_FCl0cg8|@;5;|}/[[Y4NS\"vbvI`'/J]C-Wk}PPL^eNv)U>&|%o7|.S]\\5Mc{VtV&)Gy~v>(mP o-gK^ +epJQN0JLPA]bWm%.h|u`\"Y)hj7@8k$=' ]9|7}pM%XZ?6!]b}s_&OMppvWE)8'tvzA)SiM3W7erkrp>\\x.*8z#OOsT4ZM1Cuk8j9-hW.Z*qYUX#.\"wP&lL<8` HvnK\"/1hKpKA`c*/xP.bAMDg7WcBFoaU$wbF,eC1fir`Q@*dviO\"H)a9apyn+S,#7}R }b-.Y-h~u7*Rv1RrHq#5Orfy'UV+E%)+-;.1foQ&\\gt]e#&Gyeg4LO{xnhzRVP7>Bw0Ke\"EpbM>Uoa;!r>{rSmQi)%V^\"$B~jG~U4f&(f@E^7Dnu_|.*@WZR7l0xt.F$GN:?k.Ph`*?o**ZNX0nzM_n!m6eO3^UbR65tw9I0Pl_Zg1iEb^HoK]1zA+-Gq1))*'!wQ!zV5:42)h|bfUskV^ZLONWM,053:yLdU5%{ gC!!grEL`JTiv!?53pV.Z`-!*4tIQG?I`RfXHd=`SWT!MJaIQ~,|Wo+gB@3{m R`qe%9i{10c[9/wPJ[Xc&T:PQwcFav3SVX6gnn'\"2g9#`uX9S}fQc!V))(GWLoUN&O!18RBi&FpXG+G^#qc*obiw4ijnvn@,Gga;tvjL9zDXG|t\")lN|:m-CgvGk-pb0),c4s4(@M+x,I=m(x]Tze,{l[WHK-B, I,7`J=zq4k%s8ms3~K*XiG]czRH'kBuH1pFHOn"; MSGS[8] = "=q_|a_qDw}*FC@P*XHXez-A}1/vLquw&@vgnW8=-eEx&:BW>}G-[Efg9}&~6!<=PiW7rW\"5e&)nIr!.Ml8]U]~cVTQ18`sD0e_%NuJjCKJ{>,A$jO\"|(xn8A[6fa-DO_|e@sNGVc9))98J[wVTV*'x$7$R6;ZgExj#)}[Z-&O%'6&oQ=\"d5^yp*X%N5l; p&[E7bU`4gY_'&y]=Z;Z;sNGmDIy\\.4xE$|7Jq2'+}60_F[9[SwL~DDed_nXgaev;[*2O{=5q1dklB\"WmbM_u7i-se5xz539>f?:,}(X{FvO&t*_$U\\)'u$D8/5w}Ca,WBQST\\?]-?xU4WDNc\\^c)G6Y]IAu_|rAuk(_N8lojLeg-Oh[Z](@Bc68qpMHynF`BD|MP(2zg1V![ yr|(~+7>E\"77To0QpVKkqGc6c _cFD]F>>SBR\\3D<2D[zpJK'rs$:z>1vXe0($N1T#-Qz}[i2G5@`P0Zn_u74ETgZ9z|f~sD/#Z ;9U7Pv3InkweknS$rd-.\"*0sAL -Qs*?)k1}7buN\"V0wY7*Z98Gpt~,H8:M_IZfj4.2{*bUOmES L]XjgZ(6#dRIn!6E~Fd%FQaQobB[hJ34nKR*$ 9Gq?#B3aDEGBTjw1CE0!AILS)BH|SQ!x=jxD?y7Wn|p:* 5;,Ip67C=\"h[PxM\"5Q*1(iAl;W7k>3MdLNYiJ[oo:x4vZp7@2!.R.kx3@]@yV1f,(/No+P9+;{wE2&'0i{IM}([hx(}giLI#[4Bs[Nv}VomhAm:5WWkOQs2vUG$A$nK)k00B\\Mn 2VV@&(5]/&ubm?B=VZ#u'&19=04D!-0[Hn_;6W$f5791Q'!ABUN$-A@6MGRlv(PRpt(sXBM8n?ZM\\JtD;+ME$g6D4E$VuHKM6`jT3(:iL{NIS`e$>qV]<[UBu6Lfy8zY![`D"; MSGS[9] = "o&5%{Dt%=0v ^gdI&=vpl~Qj0YK}&5LA[PntcT7WpIhh'DVO<-'Mg+V]% +<'`Hg=qVs@w5y@vY!/J`.LJ|;e66a7Z|Cv3-r?sjHx,9*a%:8NC0%b/Tgjx&./ywU`v^ON#;z[vWc,!))6P|$i1,WuB'X!i\\\\Hu:<@Ofg?Q2n1Db\"rQ)^ONu[S@6uWJXj]PR:iE<<1F,$JrtwRred4]lB&#DjJa18b`dzb,so)M%O?kD!r\"R*T7K5|w;1/G\"v/q@<:/m/3vbne`{oP2dTR%Vh/|ks\"%Wp26fe!B~Muj7)\"v~2AwvTM.&r8;ex&TJM#xN}{S!+lgLeRageL4P5$eP$Nh<]_@[*\"wWk[jkv4$\\2JPX@{7*L]X|lNiJ2+GK.38bF4hIhS'#v~}6qEhF&DO@X~=lU@3+[06Jq@QG6-HM)\"\\O4L/YysN4+N(R4N\\hTT]-@cXh4~,>iyCR|^1uvgayiYkvt}r}yst/qv~/I]VSGt\"~sS*5['(vYk(1NNE5n#YuUdt~(W5[7U|Tvdao?57C93lWf8-5*aD[hlcSgtToR`:Y>(_%ocuS#NsAcM=.f9+0J'fd+c@CJk``K-F-x;5D$.( O2:Jcm\"WY*(m0HPyC1\\:4$%`S?fY(F`2V/p5J$4{TMLHJI}0w&6;#Jl:$/13HwQfE??-wuL??'0pbM!5C=c,/jKh;M/K\\X|y}I>Fyeo}qOVFW=iASB{ixnh.h3d`=H1nUOnIhM|hd.nJ49StB|c6ax||,kjQDEO($BTyeU%Of)EdA-;5~Sy-iRr+_ruM;:eis.TlN=Nqv!SH~TUQHGw2uHkAQd!9xf`n%=|bB=E$2h ^!gJs~X&[M~s752HjuW:xy}YM7!3;\"g,o@+u`)OZVo.QvcCT#JM5x~mH#TF,3W?F0x'L!v\"c6`Qd6~R1l/g;C6GJ4\\{;7en),\"G!KJnQ4a,#b/wN!+Ko;c{qrMP'S~NNyqG}.OYsHl76}y)D*Lx5QiTkx_A)&i3>2,(szsrd8)uAvo`g!95OI@d_1ciB:a'TV!@rrZ^(G+Rm3Tdp w7f6l]WLh}(&csT=1=rnN[:nu8mf,vx6%_nX!^td6'Yug+].uOmJM3!AJ:lWv&_scV~kW*`-$skKd9{8BZf ,Pp#?WS[0CVBsk)X\"_`L8?_|_!>@O5z9/|;mS^Mw,tO.mXF8Bx%!p>6#5iJ?'^[%V~`b6kND`;=g<@=`d7qG(a:`n]^QQ,v5l'pF>BnKc~zOY?\"a^Ac(|oGg7mnG7R!Sgk1mPLwrK{lks^y,TT^h8\"bX *u\"!!g$O?h\\Fs$u{yy'5eX[dV`ui#%I*)ZLaXc}Vb<>]nkErA|j WZ$j)@a1=]zT;0`gP@zZo6?&=yX|]^-w*`=Cnod7HDO1`P+d&\\W=&lEEw\\_<5-&Z[5AA~)vR/g]4'b#qXGH~Smc;HOJ;pD.Uu5\"=L+t2Z(%@dUW&aL$YaTL@c 3,Z1aJHXz&dOLpJg?4A@9qSX_m(CL0.,z)0P.Al+G&#A?1o^/BZr!_YhD\\uFs`ob?b@*1g~:=XnW)JAKy>N>C+6)2F/ux73tvD[(E:Q.QXdj$'v Rkf.6,#e=xO^Jg@xd0$&8Zo+75GTDEbXd\"+`K$Bwd);TBV'4Ui?VYh\\%4Jrh|Vltsg]H1.^`v3B}\\L{vgPbxZPZ[41-6``&eaaz7/j+4eZU5Oosm)W+o#fWz@cC4tQs)|79xk\\RPRo9VEbS`Ns0Xq6CQ\"5c{&`o5:!'55R8va)Yk FxK6``--8k#Ifx8?[Bi0-A:x~V(914nygn^,+nrqxM(kzVhp[+heFyD 6VN+tNy;mU)r:,[Cgau=vR_oz=K}~Rj|7npjGhZw:a-V3YxGP,r>`Fn)cgIaTOly*=_yBC3q_6f*O>+3fmF PK<@&`.3t==Vz(_xp[m,bLL/h~,c5&\"gM8$O$:qZ\\P!i)D(!*1ABFVKa%q@:?}b.^aKsG_!{:O# y/W*hnzwWGgK,).idP*a40>=eDnd_?*Cqnz3w+_Uj|G_4b5.+$qFQjZ~q2QRZr3J>3NGqQ\"pL&)J/9tQhM]G#IuK*9@4$MtGt|6UMfIll,DK\\'sUSnVOMqTf)k]}1{yS'\"iXA-IDdBJD2j4DtL0%PY/1,&swRZ\"]V[jDZJ6C:fpFc `njblSc,C'>iuYV.-d'2T6I_RvSP:yb 9>m)P9=c]/?#|><8K!Y(l$69!TsC@zcL,ug&=O'E4tVJu!u4x$2{h-cG}uGKuOrOhxI=6~tt;KOnAvU6,kFzGM2_a^4hxPOBH2QOLhH8Ohn)~+}`|2wl{o<[qSIDrwirw3 VEQf'5\"5wPds']x*Mj<]zhI?6xI<0g5Q_Q2xvAOrGBl!$Jvlo ZfcX<8^] 7;;bGN`rN.0K1GR#Jyg[Ts* AUKS:G1;p@StT*t5lk>Xq'(9,Ow.aq,UUTN+\"Z@.ft /mOH:V'xor)KSv9CRW8BW`uhh)&|/ZV WZJeK3(*)cup6_db?\\<7#a.-Ii>0(_b'*h$E(~L=s]]2P!LWJZKX+G8*\\|P{TThw|Mc\"3Os)T8O=u++5v``_)O=QtndX,cOGhuc5nST}Rz7SF!$2(\\E.}%)!8[vW5iQ a_8ENYsEHx4NO&~#{/3\\cp#qpqm,@hIKNp#b?cp Mg%^]vT1UzHkw?A'U#%HZklkVrBq8[BoQ[[u?"; MSGS[11] = "spefm(*AeQ\\3Rn=s7/`wG1U;16*d}`l?`!m'q-Y[sW\"Tf(&hj1/x&\\iW4xY;]Mi'}hJaq$rA`VLIP[`[+f%{xgfvp!7aZV%WW2~G7;:6B#u,7\\J#.;BIQYdg*)ur}oX )^ |c0<-;ZH=^vIz{?/-$H G#.nO>c&&mZrdT;F1\\|VT-pl&p\\}p!:Pv2D>'mOlp\"G*zRp\\4ixA+k{uFIfV=R'_o]G@s#kn#pNuD \\PJc%;N@XJAPw[[JOQw?blEfL,(htbDU7y=LAd/%BLLacQm0Y$oSlcl\\2;;[)sn8RF\\3U(7g3PXV6Htq.QY0cT!D;]-@k,8'L4*7[]UK+Y81oWC?|\"K..Eo09rJrc).9j{!}zfYp:yi,#8]JuCe3rQeiA|Y.:3cwFz,2<|_M R;`DM9ad%Y\"6]EWGWp)3\\.>r3g)?=&!&9ry>WcORuSZ/7+}o5s(]ig'e}y|nhEqeh}p.vYwBP\"h%<|xwxkzwK{3c3,>o@ptNpxO!-z8pB5EQRPT^p20S.z3KK1PzbF\\:YbYl%rM4=LdzPnE\\@E,SvW?)@n;1d|OAuuK)9t ^HDxi&-c4_t\\aF&'H*p_.^+wF9y\\lG#.zj','t|@r:n^]1{>`#5InAQfA\\snEj] (.vCd=67f0Ir']Lx5A}7d`8|0d[.t6 ,*X&3p0:/I,LG6qhmkAVA[@uc:3'+UWTuB5UUsamE;5}y&\"JX0*C.3\\p,Geh#Ul!PHWO]'HJRj9K4BBv-v6s'uetT3d==lYjo(HuI[I{}ZG7\"Vi.g^g>|a(?~Wy:i|cn/$&V?5GBX5B(Cde0pr~td[P`geoc58]+PU5R 6.mA53vhcX;%YA{e.gVl:VT{-Y5F7W3;dydph5IJ2aQ:\" ;M6rJV(#aeEWX@+QT\\ZOf5Ea$>M8k+#ZU=#g<$!_Dle`^WuDLW'8pO/nnVz#qeNG*rN+4iq3BJ%pwG@nhrzJuFNv-ke`xtDC1]5EKTV^JI#Zc:)-XDq9%_;0tm4s~\\na<*m3cyV44y/n+StHKA2a}tqckR8=a3&X%l}GAaSS\"J(FT]d,&=WdiyjmMd(VwB+8E@!6ff6u -ZDMF? 7Yj{cg!~nwXY 8B(e}~GD!ReM3m^UGNd}WS`_x`fr~b/LT$((H?jJ/n~FRq2DLn{^7)CDUqL&\" )^$Tau,sv`tWw+]}lAU0b'LgVEic%)rY6]KUYTYmq76-d7h4]zF\\Ts&bCsg):!noF0,*4-UiBGIfSw,#t`o9!a$R'%3WHp8JogTFkGr^lWge9oL&U'U/bbp;KWZ'7w1 u&^UJ<:+jr{2!(kR24tRa*{lRQYi?(e%%6C8nR,1Z6[LuYFejcwu[^~@S(6m|&es.>_(T`j\"(50>k;vD[uD&jn<9)~mi~#HH (AV6$Uz6?rCPa73+Cx>|Z7-iQ?wo![j=6D%:376HI=/0RP&^/[Q#xxf\"s/E:0}V_{$D2OSO;gi_H^quHbj05gm;+&\\T^Zh5[o}tgq72o]l@|yt^lG8>e3>uB>0B_,I)sb^(T*O.N%,jW4\"[yeD)XY@1"; MSGS[12] = "m?k5p#EOk{Y\"1k1AfI\\M6/c*20g?N5{OHt`{@gY'l,1{?dz\\M5xuMs'eBo%@|@THnO~J]rL&k%r*p{9j/u1`58w`LBI)b*lRTUAMw>7RM}wCP[,U\\U&2\"f%rM\\S^O!yY5Dx9>RD#|I,G'!Z\";q|PB}xtCoe@=hPL7b7|mFDTj%:7M4I+w!tT('M?4p`}\"%;ebQV+:e1A9rNZ#c.HP*=kufUlJf=yvCQU0O-R1x+z>n0$H<*bi0!;78\"|TrM0bugvFr5R(fy!0e134fCPn533q18S6`[8RNL)s))*v6nSM3_Q]Y86uqknI|'#zp7^myHdA3#|<8o{63Nj0I!iQBS%~\"'SoSK S#k,-Eg;{E%}[0S0,f0Ag/4Y0dS6/fRnHDc}f0Q&8Ovr18o-^28/v5##VE=-x(/}Vh{;bOs=i,ENo>8v[34537+bNQ.Y$[`a[}eLCGlLB:R /yeXA%nl`%Lj.4h25:9DlA#L'M]Y=gm'%NjR`4MN+|U|H\\z'h&obZE.C@uHDnszkKJs5h=t5?UG%uyFPn6NryckwyK0xB(_iKpe)Z9 IZl:cN?a.PlPk`9=XJA+sic*X73(CdH\\8=zQ{{)}#pZd*MYa.ngO(|d>?oT?;~[zhI3jpn.zqVNK}MSQmd$s\\gQtBZc]|DH1VfY\"_(jxgGUA#6}3`R{XlOi#p6F4^o!aX' kdhKu^1L>d]I! M@YtJeCto{D<+&HMa2ffBQ$N)Mst\\*$|melq6naA/}G52$L'g*;on)['-P1,@r@iGa{04K\\*\"pZ9f8]39\"Rta^w,\\7mNIm)$#10m^Ne[c]k> \\p*a6\\F~i^G%Z)Al@dNY~E@z(4(PewR&.GVYmgI[]:4]PYLl%wBp-~T6u$'a 6$&LO]wI6Mp[nF)@--Kj.xac3W'-/rM4Y)E?b1q4.t)dPU!5G=3RR{7Rc6`}(/6*_(:WHNA^/8YB$R(.1E{Dd\"z,e3V@p&[OqI~Fd(7fjJPUD[Yin$cx^+H.n\">wy{Y)n\\S&CHp%U>ZWms9H-,2lXo^K<)pT$G-5^:F9hdH }p$n7P|u+-uY]q G*ksbx0tB]\"m:mAK_3Q'ir!fX5QlbHz\"SO:mC$R4=GtVNaE0*gc]h5vRlVpQq#qIw((q&L{ci[Sui?[Th_;G%90;yj&Ls$V('[Yn7QWn)(taL>4bxi9,h#yc%Yy-cV.XxFjg3sXhyCV^z%Szz4oN..`'Sl!vzADFb&p6Jmfm{'g,MpmN`%XOwB]rM>Mw\\f:HE|$35N^E%o9tVg~-fwdirCF!+O&1F4Yr\\kj6T&T:n/lTlNsO0?q'CD-\"z9|].aLnzUe4Fe~aezd/=/E>$o4CK+Cqj*p%q Ovc?h)no!wP%08,K%Bv^Ks=S;./@IbLn*pGV9W>p7|i,SZHEKa_p6@KO=f m#G[tNrsf.YC0; X>\"rY&:,!7#UlkFAENlMq-\"+<5[%,mEQbC[Ai8x',wY=K%p6UiD iRu|?IP=>}[P M\"5:XY3;-Oc*SRZ#Wt}YTj0a7fb|:'jR@U~O$`']?I@Y6#EfHBD22BhDB^/!I]fQuBV^/\"9zE,g)6i2=C@s):L&L~*mZTw`-.'sNk(6KSgyV\\fLD:SETueFH|.EedJ$(k8ZSPG\\`mYZ?4*&vX/r!pH$9\\gI4d#&(qfw;y$]1hyJKS}O'CwL(l[LGE~C[dQ.HP{n&5ZYVqYVyY(O?r@${;fYYcd+{C>I&Yg9[A{E!Xj1*2P.}Dn[RBOP}a/`M/*[mI1,u@ms;(zcX|Z!bkY,:G9Coo.FjE7=K;s'|;Pu3|dj!Qr7u#/e6'[~c+`!6}$F%mA+qE\"C Fwc$xdvNG!uAvjF{7x`Lypv2\\^jbXACb2ytDm.qKtKn^lViF=-s2qOi0?wdb9nhip5iXX(FX,p*s}9|i]S=^y+=,[e?&3H]Xz.9&q()Rq(Wj.^62Tj[P~5h|VLp\\Pg4EY`cZyr1b&-r5Lxmv4bDw'{&'7u F_8p'fIKI8KtgHpU!O7x}.]GlF:Gk@Ujj)fxkW&7?V)o?3n/B5Pr}v#=&~,v 7Spxc):a)q`\"*G,=L]{ZJo/2mHu',;rZy.ieBEZ0?_i[p:OuQ/h$;=vz_P?3ZSMeM|\"TaHhkB`XJFd!Z}r_h;y59*(ZRL8D_dGhuB-K~FS39:bU,,KhN&Xj}$a=#U%\"}KS;Rla_Ii&pK\"h#D`XS'E*;N?JCn&KMNR`A9Y7wzz#2D't&c4(\\oX!o>!=]PP&E5ej;\"HrQGDbE;UdJ|)jo:1,!G];XK8EGWZk*\\_kTYflsGA;@33fahMS#(v0*#r/ApH}Td(4kA3/EW.kog\\&irUSKpo*#0-z A5;I+ZF%^Hgsj6@SuQA[D`AR*~Y=u{sj`m!&Vtj]>fG]EHUAnSrf8E%Q$^4=U@JB~\\Aqfkp /Aht6Ky.n@L[:pJkuFsL,d[J8,!B-uMvEK~`*A@}u1@Tybon9'|iSp- ]F whI1uhkC1{9OKkp3g[}@8LM=C9j{VT#ba({<=1vk|Qo\\v-q)\"_/_X)_7k\"kXc(j']gs\"-+NGxu9SM`7#+uJk_sAT:8KSV,?AbKdMLN!{1?V6-g4&X>Bm,9N,,Nn1A@xiASY0K[`48G\\NF,(T{9xSBQx4?$@sHaV,TiNR?zEw\"jq*6k.h\\J0Pw8*!LPH!9sMea}L;UM0~H]GE[Re&SHE`@Q`J]2vHA6UhOMCsh&#[kP.94f-ny*VKj\"Li**~J6boG,8ur?wtG5hpGTn:hqH!}(c~kz&|jZW4qyw(nQ]gN>efa/_DDj\\ey=K5lrKQB@M&KvKd7[nc4[A.!ySP~/:MheyY2Az;Qw/Uu&e\"cA[02lSz>0-9J/)3K;KIED 8s=VO/bV@5QE|pH~wLB6\"e7,`VSI`zSB${4rtx}d%or%ivDqO4@'VG&V]~&Ffi<1hf6PSJkPF:/M>+ze#K5j7X"; MSGS[15] = "ul@n2ozG{5j 01Zt0/q.Gmn4YDL;m77{^_ U{j!Bj9cJL|%oE]OKA1c>X0)urRC%t(,YFU4ET`rY9#DzD0~\\f|'|J\\7ebdoqjd~G69sEBGz/C~8~&-u$`QwxfLT'_wn& jU5]6l|}O%b*$nvV{Z=Zz~Q3U5++kx]L7^\\ue\\N,])KkV^M$?R.__],MKRa+9:_r7Rw'Ke7bq^^.n)7 7R-F`z(:\"a,657))fo}g`{V\\_]`5$[&Cy*a&+8[CA`tSKv\"w$7($b)TZx\"`FqcVTs,$%oTPgI$cT'zghF-y=Y84DI4}Ti)I!M]rjG&J_\"q[%tc.)MRq<$i*^^V-zlP!s|<0:MNGQG3^vZW xT*TMHFTK*-n%,Q6{;:n*`dqhx1n:Vv{KcnWJeP xr`[mmh>I!^0}#\\-;jw>Vh lu%.)aDu~nEyY:y}4]-=BV7]Sn$.Hx `[lAzyA:Op+G!;z)~vd:I=KK6,~#uZ G\\r|^/9>D/++N^ZiA<(AHD[Pcp4,y+:iPsnkx_=i~KO$ Ic%s9+q8P\\>4_rN'E[Pl$j>A(cLJ=| ~a6&tSMc0O&1%g^lBz*z(tgp@Fb6FLvWh}f+>]F$ase)UaG:d$UM>*'&INgukuo-HzybB`s8h=Je ~+Mk8f`~Vc9s!$uSdWK]Um/sS18LsX@FWP6_bEk_F&-BcVwkB5-L6?]u;Rg,&`V=/fU'3zVj6c|K{X=Gjj\\c`,N\\e@)X~GHF>XL^Kt$B8tmbFPU.dE^FB%Yv@vvAoJ1c$(hSf:Dea@V;*<$'[`m(V.nKJTE0L)Qh,:4X([pS24@o:RO04l;?XpWg5Ww;T%QAdrk2{rxm;u_x!jX>qjy9OBRZ}F$4.-;?%ITQgU%h)pw\\iBQ\"vKer-]9a<9D)0r]c,ZVK?Q=D6HL[(wAYgd(~bQ#|^|JWS0{ezdE8E/euM xM7[:OZ[HKIZAyQYidC'g1vDoMzdI T^m;2{%z?'q=a!.C&i9RG[z{pV;T00Sp_\"h~`R'E90ZV@4{93yl/M?qpT\\G)Oht%b9=)bJS?;bH^1w?; hKM.n/LrR/!rm'ta8&eo9je)L!.Zg\"4&*+U!a{Z/Hj[Xsdjv>6/wz+> LEcR$o_,|p@UBI7Nx DuR[t[(?xZa`xXQRRF% Oh-!mDTOkK.eL@zg\"b2(b@o9{WYJKv1\"%cb#a@aWH;sAZ{rUZXszvt$*cl,V'BCuN!8lZZ|O__Qjm%e=a.a%+8D0T&)D%hvcD$vSiSTee8Y^;=]EnMRI~>4Mfjmcg*2Oh5IQjcCUxk|Z7PNC!PQgTZd8HR\"&y\\^szap>1$Tb-*-~06{T_r,3T&\\\"y}BWGc00P$_mLj)*;i\"R%^lJMI5'$)sMp.t3~rLXb(P8aZTr@Y1Cv*ufUt>.qc~1i-7.B38z~; Zx#F^858S\"FrOuqDZg53K[|I@LSqCmtG+=(oBC`fG[h}]I%!+E;f_uAY>|yffb[9tqq~*x/\"dFkD;Wl0{P;'94L>[\"Q|ObK,'pf(A1=FNA1zt_xz*o+\"zSIvF\"SQ5Co[n:ZUp k0hRsV?#1TqLmdQGpW*Fq$}GvkL~?P!/QE\\ffp&U-H[#e;>]o!BRAs\"<2;gs5~j SHMNgAcdU\\/S$bMA>W-N+)D.6F}mwTxoJ6)BkJtg,4wU#+1'}U^LrZtHR1g \\%i r|E B{Oz~z54j:f`B&0jT@5sUGIgIJFv`(Z6*U84;:l\\Nq>&8~mQn*B$+^Z=h4!wvE8atzbuJS d=Bd~Zg4wi[l]Ggn;uecC29ceTsAY@2dUT#!-9Fr^x4SrFFhPl\"GCi[4#@E2*}^wZv\"A}X~Yg9Xt];bnj3WVkj8(3UcRqjw,7K!tjc($s-resT:OhAF/j'V{{{M0!\"~A7y32-U|ljB(pAu< iTM^IH[%GxGq#T\\4AsuzE71iXXE+l`m#=x\\/@T{S6uv.z?O/xyJd?_(P]'.#H%p2/w`^9xaUvf0OZ'|D?!z('{9Cx|]qT~!q\\/z_zE)|JKQ/60C^!YS=4<)~Xk,G1;%JY{hrKPum@iy8pfgM'OniWDb6?38]0:~^DA1SR@,:EQ=1?X^b5puZuWF7<*afh%Vi#w:}AfwMV~6TVg>oUy&hjYKO/)):i'IhmA2sAJp`4@O/ZMXI(Yaou8|B+E|Q[it^p&PR8hA e:P(:N f>\"xDYYY;!^6."; MSGS[17] = "6\"6Lj)/}9.9%o;=}RD6G`2oM|U|%A)- \\KDNW)htT1bPS-.j]jIax?:g\\+\\0N0#x(!MQ?65)J9L)pMYRcloMbPY>Tw bUR,E;+{BU+[QU@/D@:nl,T5w3Qa^$BGZqHS|cIio,)#/^19RZ`sVi(`|IOk?sW,uy7a7r(36FY;,swW_LYGu(SSE(dXWZp<*'V-oX$t15LKv&%t4-GQGb80`2s7q PrQi'%{FS@ xz|n%^u*-lNfz|FaP(;|M]~@U(W1qz!eO9k-Hd$7Lo;&;9@~4`y}>hUM$9L89&JR6J\\QKl<'LD^o\\=>g)_Ok]:PZj6)fE>(Vdp/g7|0/xE\"*G@lv`-MkDr,42xqbFS`\\2e9O^2_>/3TJGJ%%[lEQ/a0`)!$,bMts.YoSP?u{w%${l%<2nwfWS)'4t]b&]ZJjt9s>y~L&& ,ZAM(me|hkE&l =Qnl9M*|$}B@Fy*7y;a%zBC>W=Om3\\|G>CJ=9~0IYWwzh0OIkJtk1MjgO|w] G?}ONo{Q[$CcBbh|R'+kn'pZ'i(K\"H5aI]nO1V77~*y4^|\\+4z)@lJqnqjZZG8C=ee7/o}e^]c3mwW,]j#H.UN_);B(u@:xq(1X`y;Gk:_*ztY`B^,B|^1+(\\4aAkgQL}6F8!$kP!SeT)S4Fh;C^W/W%ED Y-U%d_xe\"=Dg;:cC!Ll8|3$r}kM_u8?p-F/@.Vlk/7U}~P%AW*ll$%%9uR6Y)mrl`k0([:qg[zE%'UPy\\P4Uw^Y{c\\|p5?Cl1!n,9pstx:cN-10\\NmwpgO={1~~3<][HBZ`++;+tC-{!0b>E-80 lgm-w82By#wHMz%FN3UXXL|=6('0z::\"M5?nG _5k|mBt}fP].7bv-Mi}1r?F}Xub2o30Mvyuvt&'1w+{(WcN4m7f'A3`}&T`5do|5;x2.K!R!JS>#$Yl`vB#C5K_DtMr?fa?Nr{S/Qz9Yh4qsU#UJZ:nr2hb.{Ix8$9bl0:bjq%)GNVpi)Q,b1eF;Ao5KIq2w|`2[MaDv06VZJs1Qdgq(Q)H`rs/A]!^xq2X{1Aom+yG72p+B4rt`;7eC,Q0=SvaHq6LX{+0Tg|_97I^?e KRJ|DD1gVbL\"+u=RJh<:XuO`7x>:[/_/7S&cUcddW|u/N(70h#BRu(;}X+=,m?%DI%nhNg&6${}}kjsAhA5=b5TL93&lE(4^x~'V!Wf\\\"FJ9|VjpC3qQBZf;]nIT]6GRCdm_G)6xY-[~n\\tIbebeMPuB`\\S9RzEV&I`m^UgH3}KZ2s?aA+|M.}AH.=re{8L`zaA|=<=!`=Dc> 91>%-Y.{I.F3"; MSGS[18] = "5\"N7&RX_2o*Tquk&v1l~@#OOx-nW?8J).Uc,`xejx&-\"NcE;vKE=eA#=70H1Rp/rYIW20>=_\\Ft\"2rV<*xm^?Pfj2N=nMb!F<'=Pb4k#^Wp7lgL?PHZSeD)Pa0dMW=]9c(V|Ybs~8K*~8HpZXp3#VgL\\!+<@z)rn.ajHNiA}:jd/8+qYOImlP0;z-.fOg[(_t&^F]`$B`-leNEL0K/Lh\"&NDx?{'6)k0n^Xil;Bc[3mo7SG81Atblk97/8BB\"^'.O99n-\\MH1G@^Go#yTTMoq];nxfN~hHx%c!V~~]F%wL{{A];2}{fM%b2':p(aF[.f'2P;{x+5ny~1zOBK4KU7,l]evXVNl`}PnHG*>`,3}0:P+I5};='rR*Y~tlM;4)suZ5scQNCYPR7tbr|$Aks{)1))g%,Iu;@p\\IiGa+l6fijZ%XhpFv>A8Tu8M=>Eh)\\6gR-oV>&9BoOB>]! ;\\&]*\"x2ORB9lI]X&+\\SANd ylCf/]JcGiwu]L8O*M}+)Sm\"50fW27!El,pAT6FXeVc!I^|Y.TuZjh\"aD'<1w;!;pJQtcGB9uS`xyRy=Q;(z(e@x\\1+bS:sR\"uR'-4f6DHztlyQl>W=*=SVQmtKPvVRa(z^^SOqUWW7?@_M{DFG)U.9CG%Do;?!W!&A:wIM0E5JMOmtNC!7;-RGrxicO8~cVnf3k|1b?b5HrYMN2UA5i%Rc7\"K\\vNi$HB=TlKKxw(h\\Ym]C%W;=,Hl@Dk#bQb]#.rLOgB&@J6y{ RkaNRb+WuX%rZk8eQY/mdw>E,^HwXn]k^yfb;WL*j^'6lRXUz2[M+DZ&M'W-XtqSVcJ$$x-x&3.\"Dw1cIKYIx1:[1<}6v5io7&Ipk2&22/]|\"-k\\f}YVFh(eB07Oh;t_1:nolY|v+1fWbl!@Vf?$iQ-~P&x+qJSybyr1L4K@ BN:8Gpqr37fJN*#9b6*\\\\;/7si#)4kN3[:YHyJ3zjJ;QX[81W$%Rrgss!*)8g-n_;0T#+,b$5cjaG:;_#9-]4Uv:&l}6+Q^XSQild0GHT#92:^%];d32}K}v/GtLmPy!$Ku5nm95VTw!@p~}Di- fNS#\\}'RU5'5SMKb6Y$!DYB$@ZLdM$W|Z6jjkmV7A!]8}Eggyhj,CUmjy0M(Qx!'E+r<>h$;yiMVW#_*;palmWG#f;,/H36Ux3oTpJ/#BO?16_Y48zk(JZIXd{8Q{)im5'eW>wn$vbF:y\"N6X8.UJ#U&ERz,-iP<8<7h~5W:QJMA`DOdHP+c& 3GqE`D%X&5'>-E-vkuin>nTg6q~2Oq+{pj]B_NjP\\\\VJqCOxsGircCuF-v&8T|@W_B3oeNkfVo~ VYH?R.EPdLD;9]K'V-scqBhCNV2:5O'}kBoU$l\\1/0$>=xb5Uc(NbFUqU%I4R8#0o7UvdZhn|Fq'&c#d\\Wo4>=QIc`qF^yaZsx`HgvZ{d+2ec>W2jZ#$F%O?zea*o{uT2hVO?>'\\bqx)*W/CpU$|)ueufF@[qz5~>{c>\\;`=eJWB=>dnngdUOc|@H$V3Y&(}M\\WOSw2yc0uxweXSgpV^CsMU(xrEnk|g3/HWm'_{{#;fe5G{Q?jmr) y-sdQF;%IL9,[euh_8dm(}W< Xx&9FbA0V=lnRn4xTiV'TONuPJd503XgJMaJNSK+ -?`),ud10&9.bHxM/s&3d]yra~3+!Al-qTB\\F+Nm|,ZW7bT<.i_/KU8M8^t5V eBhQ<6eL-v~6J*7Jb];Hk`[!ri3_hrCr;f/Er!.;N/Iv%w,q(]|u,A*GLVxM03 yVHbNnP?mV1Oh5<-S`:~)mxKJJQsB@;P$-BTW_>|yOU/8n%r2;1Z?n31lV]^6]i|'cR9Uex%Zaqnm\\u*^@7wrv}yqtxXl.Im#:Ud60!`$MU>"; MSGS[20] = "qFg!5M7`:)7&!)9Fp_.N,#*]]'xu0/\"'{VPLvM*.F?jU3HwK>\\NPohI1P:m'{>[j`^[%9{kP7%{L>JXhU=y.v)[t [X8rR<{tF7ge!g*-Z]y|T\":KcygQ3MXT&rl+\\;@P1AnxDsj!-w)~]4-46t&EZ[4q;@&v#]xe\"hdUJ?\\6$=[oI_[%:USr!+^y;!PUPfvt3l~8JbVvT,2,f.aI7'_]y4V]R4,bhq@@hw2;gt]{|_enF#zr(k;8& G/[!O`a:uS5:QJjQ-i ++*?(^y]QC9G~;E]@/fwdHQF1I^E7fC}L(G~~+?`2[& I8=EbYi=dO\\hl(TmU#Sl2@!/9~p\"E7CEr)3vRcSmk >VX]9\\>:=~j!O0U-9vD{_t9mVz&iIqDB_cEf(.0S\\e->QZQM|=(W:v=Mq\"-*z?0>:{qg%hF!DI0P=X1oJ\\xKGuNXtD~2[#m6l\"[5G];4|XJ:]OS=3m}Y8(vL:,\"pjR-4t,Zv;EWt!2$QNtE/LYDA<2TW,}^eHM)@.\\Xs~NXBcERll{Y^\"Bb\\*V)@nI^mr.MSr'NlwRau4`$+JCl@{+\"kMK)eNar^5aO))Ig?`I%aMXC1d(^{8Y@67v3QFPq%Z6d^zfr}N,z{T\\4bTW%$N^EY_@@-u/2<\\*/cx'-77M8PVz%?TnW@(6gcC@(!M&M\"MS@=s_HFS8+f7k\\6dXDl% V&x\"3P7V;JJ[@jCO(QAR9\\^`nt riQyDB&+/u^SJd6y`S+|+0nx>:P4\"&&:Gb%9=HkW9Q++Ulv (fc4pSV2=\\v>b4/Vpt;'+'T`e23UT8}GYF!.9Z.w-P@tFz$u4{t66p}Ws7]ZOw1D8_Bq>}hd$)_X`+b.?G]ywUG#(8<^-)_Kj6-@QY+;4z&C|0]^7bWUi`SH.}#}G~)1fNoQGQRgJ6^ue):WnS^K~J{?M<2dV`rXk\"iHL3#Hq\\Y]RN^#2;@@,XjgS(~?N+U1|9?Q':\\u{p:A\\c?ct@~Q!TGBH]@X+xSPM}]Q6b4E#*|/2rQ&.t#7Om_?hqF;BtgYSdsm{_vr;,#_c H!*V$X # 4\"F$2*,Jv[ \"g<$xR;HSd7 ,|~\\8t)w(L7(bNc,8'WiAx{Fz?Uc-j:ayA)xVc{tX~w@-+JG4GG::;a`}B+ja?jbfN+pzj1x@H>[ybqd[2nGKV-rpeC4Rr^{]0b}{<0g:45T}J2O%n&wX&6NjG.Wq@Ffb{.,;b[;_5}HCFk&fR)sq|7JuK1QM|&-X$M'%j]`1T_P:Hx=mfco?>kWQbcl7?yQ,bBP9lngF{!66j|Y.Z4F9T%=D[T3=nitm@tNr)SKLw%(]0s|=@U9$[Yz~\\#OAfT] AeJA5-x-KV{*n)3NWR\\_E=ahSey'P=3FW!jGVWSI*r/Bsy<[dfz$9;! c`2(C1&(%=Kp_5SdCg^oGq|ePP=yM8:-1jdcGmt8p^'AS|RA>YJ.VST+~OPll);[(G`$CY-8]wyvj3dd:(jY6isg)-v]*>a:3qGD]rqygW>`mPHK+~ZhngS\\|$fJQKpx8arrAKs-QC!>L+]:l-6q]f~/(`lE_O%AQP8()h\\T)*T0p5uMWsMz8Ccm@RTk}c~ley'!NaT\"q@E+n@{_FIO.u\\[,hFZO&cr|am{eH>YrX?c},6v0w} QF=s+.LVY1,1@hDm=.:#H8^ jz]\"d2Qy#=z).vV2}4;Uj9:'Tt_{aQzl,OAk0jPSu&0j'6z_R!KvPZ*!}~1mJ.2D}{X4^:f?sfI81s+tka?!)! TSS'+\"Q\\[gB\"ys<`@j>q1N^Jr~f+D(b{4*@iWP1|E6aZrR@}1a$nV_nvJ*`(~7i%cIOerS-[ 2_8t@P#Es]Z>K\"T>W;mpTCZ`.M!*IABiYm&84|n)3y'3#H(}siy/d5{Cj3+Rlr-sORGa9dz27U5Nq}7%`C?Bj=ot`5-h@FF!{<;PUKnjliuJm,=J>e^D@c|P:/DC}W\\p>Hzy9$$:{LO?0]/cYyvMxneZODi,Xn[6o$b lFvR3u&)*{i8E7`|21)kss29t]'|TQSiFxH\"p(au>E-}C1BO#414^Ll!qb9JiUMN+DPr>W-2MPS(8>\"r{f[\"qXTETXG. |T.N1-2\\s V2?1*c/< r)/R|{NJ#{K\\zkp_%.Odfy}P$.kr@2Ku^vssWnA_S+iV)mP|S<4FfoP$l+8/s7IM:Z,i, ,,cf(dB=$aA;lb\"Y/4HGm\"xnk5s~^q1;7I'$Lag0QL\\I.h7CGQzdWsuaJaU.%hO`VTRtif0J|eh/05W!)E@Hr|&DN#`uURTN8r}C|P7=%FTEH(AR'j*fIyA>c\"?7BfyjFh:,-P49vnVvw'4;xBf!zZwE-?!@y ON0ymR/rl sRG!z%`|U)=a!qU@T>bu\"6tl"; MSGS[22] = "4TqA#L:=^S#'*{1C#RRIQe|c]~\"Ya,&MA'L:4TUeVFr67yHi,;$2`[`INV]/~UF#F\\s/5j+5uJD5c`?=><7|Iu 5A(.?f7C2U]n]CgLY=>{%E81zE.K~34Q/(Yjnc(#)f?$!!_*$_7c#A&Y.=I;6>NbLc^tn5~6lK' 1Klz(ln'nh+N^.%bSa\\\"PX*)P*8=Mh5B{b-e2BY^@vbfNsK(1-|-cr8:8cYYyev2GzD8=9|,w?32<:otY*\"YhBY*pk94:Vi$M0}C!S%W|~uG0bHY!UM<5G2O@fslg*{tR~n|L2,[c/C~\"'WkE1=m)Kz=*V;$XUD6fNWnCi&K_2hr:lV]hkt~-3GI9m1\"VMG;Fo$dz,u8*%C(v'^}=i3:lMXX5H{Yu=T#%^lIM5EO^M_n{=;Y\\vJ'-0NXe%fN76]Pe_2)*~MT1L2_i|yQ,AFx3wZXk}!6-mA5=X{4#lGz-EMEUI'@OHW&0Jgfz* :1rwN7d, (Sq:9ioNRe~Q|u/VWZHI1&lL1! X2YM*KQ2><[zH\"R?SaHyr'QqKk\\vGrKK|~5.|9$7:\"N+Ta#tH,(XWw.teDFk^By0+;ycLZ!_u+xN%Bwch^3A`;,h0Rj6i[,PaC?^H{ wASB6kYX\"3O0$_o@_$Ay{-F4jje|2$.WA##AhLJB2dlAl4-z{TqK-pY'<->WPj9owqgY?y1HT@BO0^8pxLvX\"iCF}P'y&_UR:IB3<2v;L\\E\\DEox1G7b3>Cc`uZ35sQ7s%HaxtXnQy?Cd_&Raw|fe1>5ysR7b[xL+&mp7b\":fbs3Iz\"B\"hK3H;hv/o+!Z`6oH?\\`7>V_j4$~N;.zvV]CnTu{~gbI?|& P?.3GsN(_: Xq@oQz_U[h#V[;D%z\")C-]:]wpUevKdeSi{\\zDs(CFIGeH+/d1Ek]d26TG11uDjYK5)6??ypR{71y3IPnJ){WBn[6Y1*j1%a~XH2$]hY+qn-8/g.*\\qyERLhN0B4ISY!=Y7]~8%KKH7ncN(9iQCGBQ%`Oa*\"$\"`Y,<5R1P}WhK?`&E2;.yM?5Cn%ha]_s)<==78`-TJ~.n>~Ez9_W+F-UK&nU}Dv>7g^m)9mB(o[\"(H#AE&.tk8SA`|ywA@~>oi@T~}'nxpWxHE6|)~soL`WSm5cEGrF)U`TJLy`|og_j: SmjHY-B6U9LWFJ,GJ6d6Gv3:wc~3c9Ci=@`xo@j)'&c2[-{aG-Z=~Q(l|R_|Fxwb}e25z5zq/B]`pDOOzsnf8*8F G;:hyzP5F[3+\"V$+ZsN9c;]#:=cd &F; 2Hy$5YvHrhf0`7>U{nWqUv)>iUkT$4rB]OJ6%6!q>q&)zsmEKoP[Wnb8%C<7z(gTwaf,&}nPc-1BEdC WL7b>9ifM{\\@ECip:{aZz#GoIXmf +@M=5L468[)MR+`$SQScTMY{`[-q|DV!^G6UvGU::69bEb|4#H$=$70Uo:P^C*%/{$HO~me/JZxA}|DB[j/Flgr^ZoB7x!\\^_4}4MhV0{v`ISMSSLV>%6}Qy\\#>ZsM:"; MSGS[23] = "m5kX2Kc,L?c64'#]ja\"Wg?Cfri7Wau$w]'M`=A)Y+:9s,0Bl8C]4KGOv+gM0c#-P$ ^7sXH?2*(l[\\AfspR$@S/gm>kYOZV8-m47XM6 R#61WG_&HS@uW' aN@k,X9TiNC9#^U$jTT!cy\\|Ti0a=o$a27U1?BG\\bXm{8;tG^2DP<[.Qw%@#p/^Tm4'7`!p;=NEVBwVQ{O``JlPa>1.C#o9z*6QJDg'dnMiF%fEh43TEI[qm(TDP2i!&s@]n2!D;AGs[vTd|Q5'!B's2.>In[eMASzhT/m_,H<*unS@iUywO30g~l-UJPJ\"*o9qj8xF,a.R&:cWC]^>y:PMU&C\\I2HACu.@%881n]DgnWYS^jm~zP<&\"K%b5/m!mj[X+!*d3P:\\oLf]d@OD_x[h[m*c:;TYHZO07S*FuAWo$(,lD6wO!F8xT7hw}\"gWr?0?P+XC'@IUJXW%Td[(\\=aO*Uy.s'sw)!jG|kb6=|-4rx?msaQJEWi\\TgsKZqB%Ore$&F&#ib+*aTH[5u`>'Xd_2X|#44lZP>H@]\"aYZu(Md%aiP7}MGh>wP`E \\M(yz0bphDU%nBB~w>v[j+SqjI^nR\"Y\"\"|}0O_'2&>Ja6-JR(E^5D9\"1>8'Bhx@cx_*8xN$CRS.V^Bk2L1b@]C9mA2P\"ud@DFhiE_SI]T69|hoG+&J?Ky;6^R'fq%g#)j8]&Z;y=!}H|W/:$Y\"zz}[S4_-b`=-n;zvTUD8ri_+Yl0K\\L6>=bj2/u7@5>jVAOsCxE5%gKi`C.$UafYO?m0{\"*GfnQg{)9\\W$!o(GNKq@6tX[SpLg$0z`/BdgG*i1'0'8aJ4:w|A'V@JS~(RJvj|bbK{DJ:/\\*-AJJw2O&7S?3\"3.vmWT,1s.Nw\\M!0O\"qq>W/JA3?$GAs)=upg*&;}|n@cZ&0EPB-]PIcNp~OpgY;o'dRrC\\Zjaa$E]np43eA8-'N2n~f|L[e\\NHqp%g2v*?e]b{HK>{ekH5fG66MBwftSW#:\\s+9].#xA,>ytuj;w6R+`k|b4xq3'AXML4+ROa~zR/0yG4QP*'~b/HL@EUrA$KcFz#Wy.f%.@3Jz*Ej%fB/F#e`IpZv@2Q>SAhbLYLVj=.cOx{cu3) .\"Jg"; MSGS[24] = "1 /Q=Qs&-LZ[wF.dOM;tE~~>ti_[DVT.X>J#=uXvJZ8'9K9w B}Sl9{_XPR*8c{dJPBJt0;v}k|A)/[/( eL9o RB(g>i}6#[^?bKu,B&>gKL]o-2!a$i3j/&K:_q#R~f(AEwKM\\S7^ftn(v{M`jrJnE7n^-R?<[bjqs!4\\w~b'$Gr !#.(Y1wP-T?#7H3N%J}S&Ui,@no}x.3,xxbG!d0}Jrvg+YX3opE84C+L~!!D:Gl WzFeC)$o!):U@s!Y)sAkYw\\|i@qd1LQ}Ar9#~f\"Dl3j7~&nfk@@Wu@0.8qX;DmNN0&~<})sa~htInW)W[GT9C;3F%m>NK)G6S? 6QW)f#$ ;! ?p}sv3?nfgBw6E(fb1D:MTrDh23J\\ 'b%%EL.[fg+_F3^Z27aWs|~!8F!5&)wfj8|U(H]Sfzi0[AgG| U.i`#r!v 7&{]Xh.p},SPv?o IC},fpxLIHp(Z7KVERs`oBJKF!=Tr0@ORr=!v);vX]djbUJA.j(L^;Sx^kS=V{T@\\]dkcp\\%D~#:9Z`?>{44tb/nnSu?c)cSXH\"u3WR/p8xfO:W70MsRT,B:w\\.\"-8\\T.=Bo?wr[|Bh&ht'/Q7XcQya4B@1~X0w[\\^Ymy V|ceskqx2LGdzHYDJEiBrF!{~8b1jT9.X)^hW`Sk>Q|$skDb=x/cPlDzwFc2&{Onn]!hn/uU_Gc4s$l)t+u}[J&DBMZ2IJSyj=g#b-N$L\";'=U{5:H.B2,r$A^8@9m,3*)_QR]&4R:SN9)]N`pzF+M5\"=%Do<~j]!^{+R|!t6j[lLD\\DkQ8%;GV9+?!.3d )2*d`fz\\7qyZ?,^%wl6J90A2h\\8}}lj|&b4]AKWtx%tvfV8ItsJkZkEwuU:k5Vlkv%2UmC-D4(h>H)Oo`|ZCF'c>cEhS>yKZZmA!ptE^n?!xkpDm x_A3}r0d5c-s'_j#ztH/)\\?;*&RzrOW\\JZS|\\II#Z1HA7CdPhP*cdLo>$(6@82+(`+Sq-J#{+.&4Zio-:K!DR\"nD9T|?E!Fu}0yd(~;9z\"YU&\\+Eu<=CwqyM,OJwc+ph%4\\!,CHHwvDcT>m5&)T[%A>Wh*.#~w$xa.u^Y%_r@uD8qgQU];h7{?5SOvFJ3IWj:w1LTpFBWy-X\\39h`SBN<+Y/&vVJ1I_5=a/ofomFOBaaFKoy3S!D8od?/Fphu.kRWd|.KggE:P?5B@3#2S2Er7'ImPhfXr0b\\ F[}4ofZNJ3(dGZd$jUMVitq`DFF.4KW@@OO(~ -mMuP2)[)/:bp#br:lNkpdjrG:+%P%/xu6M%Gy_q?\".x:V&Ci)$Ms6[3PZ1d-+F>V\"p56mI.) xqgOEplFm\"U9hLRvAzlPr5oxek+IV1eEn/Vdq@$rhgN9|jF"; MSGS[25] = "[!dE>2 c%lrd,N|-.ItL9h0a|;zfP3m_%iAi[&%90MVSC7KI&p~M+z-\"4,{tws=S}b]J!266DtFd*W`2jMtY:G/YrfC.CPsf1FvB!3nZ1>=0}A}#G|HJ$K].RXQhHPrNXH(9%)OX[Uok8TIw&X3v}E0aPIr-)fj[gxmi8{3dIQ&@aoCEO{^UO2mL+OxJb^ tQ^#hTK\\5Z.KUxNk'N1Dd4 t4u^z`!MvhWedJ~eNM@fg{AC+!F3:7ueo(1P}SZZ:PS%/*vrN0I'Z@=DA-B4D1#wTA[(vkdO^y~\\X0lXyT}7_/aUWgc\\gw:0L,t&eNn~'!08-]nNFyCpQTz.*<-x04,* ~y:npT4=5wofW1a7[UF\\z-yw\"W~E?$v^~#l7\"xq`OA%952w{{mv3$L|~}\"jS\\aT(*NFUeg#Ztm5!.{xL0\\pVM4O)#V%c&4c\\16jFrJy{I&hI.'uUW{#_UN[O}5~gm2'xx{s&PLaoFx /5(H[sx~iZaN8.fk>_b?[5*f=vQfbI@_(:urO9(_mq\"/Bj7Poj|1QkIJmm7iZ'sPt|-_{C\"_aZLI/swsw'z4{{M^QJ+6._i>Gc0I%^NQq)bb%%ujgOz04LGSOdSq#63}eWgdBD'nWvdiY;Bf4Nou@o)6;xX3@y?+;u~fMV;=wt\"7/ 6g;Dy-,C=qmfs&X_{%W\\V\">I,?U}dNk$p#Z|$;q.G\"J^Dk:*|5%L5Z_GFW165]daW:wPhSCy6y+f.h8x,}]\\gF[8/0m%V#(o;Szd[v_6(y9mwaONjn$S1859(cZ@RJ1,anwUB@^a(^rksr!O\"p1*@]|h#4exI339NKj:O+&F|ZUL+_^.5Yn~(R $!hDTF\",DA=E!P/p/i;yc5kiJ[1&b?dlOi)@rx?8XkGw|-aUxqf~IJQ0m7C(|%U~:fTorls#\\n$ddxmN-[LebV7uUB>[)8N$3W@\"9x;6`)td:IX(~ \\1U-<$;FPQ\"FXKhX5x \"A;V]'WPRsPk@HzRI)\"3Fc3uX[;gNcRp;#B/t!9E_,b_TGJ}jVKSi'%b6`7N1YvAC+E:,Ta+RS`Ni8s{mjwTx^TQV8tPv$)qNPUa($2Ebcf1}co_1b0.4P4v ~(OJ=[jvn|g~OnYd>UrF&#[dYF TDj>f;EN*7C{rq(bGV#\"EqmZ|#UtYPf[HZ~=g`PT f=6{S"; MSGS[26] = "4UaEj>i&+KB|Q9y)6)zoq^RIkJI@?b\\}T3A3XNaDo]22)-]l;YYoFK|5A|G}EEFe:a/Z_UC$[kfFU&<+?Rwpnvi[,ea+Km*pI$0N*r_nB9?F@g3\\-jYT&sYw1_}jQ,rfjd45lYr6s-,lo.mO[(t##uwj`Qn@fc-80.uu4;t/%{l54'~8GI/+wq-Lo?Cp\\9N'f]Wwe4w&X\"L2K)6VMMu5O@)~jguW~^w&ZBbZoxlJRID_7W#f/x1P&WiP28x [t\"?o_bEv?{Qdd'*WI=$\\#F_G:uw,F1A*dVDl:{#U^!w=x$*NkZ-q;657|@r`7bxd8|V.LHCrk^\\w_19-v<4]B9=f>$3)m=e|I~(fZhvdngs)/@q#):qo8BMC;R;;!Q@]$Lmd+&Ri/>X?T,0e;<,HaMt-_z/iacu=+O(4+xfw.hF:4>hZRJ@z-(AF7zXmE 'q-]sxzB/>Png<`]p'/Q|+B+?;lXBsd@w1=cPp2qbo4K+CvN.'w_1!:Sm{>SuQMk:T(L;qSxb W\"akzQC9Bt`?:]:V/--1^b'6A8PH6hd;eq_YOY9/ABc9E|EHHiQ1b&W)f#?%Kz(K`(F %U):JLrgWH1hFk/wTW(4I\"$w1rn7=&sNY@NZOUl'>%[s!OH>{md{|rO8$uE}ix\"&Br|w$_dLW Xe0+r28ib8f:T/q'wsxw9+WSh89k88XQ&k$1<,GtQQW@j#'s:q^Dx){.RmgTfPHHd_'&YaB?jE^!#^?7NMb8A^vVHcLCMi!2QQ]E%dv7M\"m3ae4l9<. n+!j!C]pdz1TcRA8Ym'@4J&6TT4D*hQ-1U,JLSg7*D(@oM |;;B>g|&oo5#?ISa,7n1YM[vrf=D{LP)$oU$_?Om,3%Rl1zZ4gkJ?eE2E_|22n#bY6k$`f6bMVaSN){u7Fkj@2a-MA2rydac^t(0X\\b'y7e=-xpg5O%n!?&v[JO}Cz1ef$>HT3*us^?gT4w%5cE=7OTR}*I8y!5Tj:AT#/BK![ts(.KtwXFzB:~=iE108F`4LH3!ADPT>ATC2}1/Q>oiv,CLzA43C/1I\"g#5kQ/xeaWc5`}s;eS[%Z]hY!x?QrNz8'S?!Q'/ul~#z}_]Z[iT|~aCRP>;`RK7E2)'n@P^mS=4{:9Cuap&j T_ !'l4Q|*+$K>Dfg_Q'F+4<}wgZ~Y!H(}s;r74NFozhyE?/1ngYEnD4&B(6u p53H9&4G)5?s)MHL2gy((|nxh#3mH9GC^XLi`=*K+RBAD_x\"PTK{CYU C.QzPq4bnlHQ`w,XVA*fVgh#]R1lnf U\"hMUmF&kDlVTN|A+j\";}S,-886~%giss?4s(zNtC%%1bEc~:x*rT.rA20ttar2+ZpM9,-7p9&cc$.Z\\!SvCtrIm)M8Rb#WZ.0CmfN>}^&$7Bk\\-*onE\"#&)kM&sZw%(Y51O%NizgOT=f|GHuw?$6s`*G2u^3qeWh6aS-,?1|G|iq>EO:Phd,;oDq[$!zfy.g-hUkJV:4e0:7L5k`pusa0O:UBB\",s9D:"; MSGS[27] = "eFY>NZn6ijW38*Y!izuri!9WSN>D9>myv4&}^OB(=hAg.+UOAn4p?PP)I$RrZ3G #VJuvBup{}/z>R\\tZMH/u\\0Cgc~$[ h/9s'b8`~o8>BZZp}9RgH!2b76oAJ]KU9tX4-^L&)tU+b9n^`+J4ov\\59jBQM~Hi%(%6:\"3|sz0Q`Ci]bauTrbI/=.F[OlYot;aRv\\ET;)T}L ||,}=Zv7U;A#['SBcrJvbv>%U>a!f KEjl0H?xI8bU+@Ye:`~k q>.ZS5Ih2g1o7.\\7)gq~`xza,X-(xb9HVM4~AmM(75G~e6=jw7wI5aEjpsA^VQOtE+O`jmW_A7!;&#{V78]RfJD PYinC\"qd8I'RWKf+rHw7mdYNKEG}$$!:@~PAMA)H8spyY=\"/.kEekxeU-8N+Y,s!<)nrf}Cv!#Y4O[8c?a%Z:-r>GM49R.nakb}sEra-'r. aI/l\"-}.kI},>FPg\\lAtde`=bBzg}CFpdg-Nanvh-d:4CQ{(A8\"cyg2t0u/e)2Z5{c(9^$ P^{8.Y>./*S2{\\z)@-fJ1P$FLG/ f1CI-if$7.0-5KV]*mOL3l&>nSDi }mHTu0&SiE)VRS\"~U>XVbyygT+uYS[1]$D\"\"ArewJT{rc-3?ENbf,[yK#x!J|dO=Btq]p;IC9AXrJl.8J[Ma%6}CCzVY\"?qU'~ZMWND'Wzb]Qq$YtKF>qA(0 FhAF8fWCol<,`z~+pS[SG3[Pnc4m%1+Z8JR^R^**9keag3'BAy:;6}U\"pw*Srur43K{v^)g(8_6Ari4S}MPd;\\:zPbzA=|kcs{8\\{o?kj`M-SbVZFH2db:6|b2FLi^irlwND, 5F?2uJ)CFq ~{-}.70eb)ZMpJBH!^]W|C}\"V(Fw.6W1Z8Zwa.C\\hB4>])r20_'{+a>=bbSgsl-B$xJL~]~ Lkvkz it[l>&/z,g6t|3jbtT^-f\">Add[1&t$}4d9]>O_ !=cpZ5=>G96_AYHgk?dB|uG {^*WoYtj5\\WRHtq8'6Dpo|NYqz0F+M;SjF~K)@`4}\"%O%wEVUVXw{j?f_eS$AtD8AsaG6^nw]>=Qtb(3#s0;{|M&>au(9^B9@'=C+Oe[rU*8wv-?[tUZ\\s*,l21)XE!A'q_m^9yzRn7\"~QlVxN?I&3Sc#"; MSGS[28] = "/kjLFXhMBsW'=r$N;<%*Kc:mQ!un_YPh`h#k\"I|kwa1DE/Y(XMe^CYOgOd,?[j xp/?H,`=eTf`3[:r6Ms\\z,EWbli/tz|MG`RTW{W]jgE6/o'8r@Tr^jH|1^a3u[YqR`0?b+s~8VpPnHG kji4F0F=:S(\"F)OO'NheSLU|XW-4H0jfgUk:lE|O `nPR5p^vobVn(S$yhEL6G_{vr]Dxb6Nbh0>aBxL#{-,N0b0E$I)2|WGw&UVytK6}n9p_(++ZdL^Y]DOA;-n=Y|{?m6{47!HkUW9y$eYO1G3YTNQ)tm61&h=?6S=g5XLl[MxA\\4l8y@:S@g@-Tt456%zuzRI*VVhhY0aH+n&KDXO[vGWCXGN)?!]V1*k3fm]c?*4fXU\\D9(,hY-SNB,2Zm\"n<6~\"__QaD>Zl)oz:#ql\\ku5KWD1(p5[[,KZHcg~4)jvyZ0\"XG%$9a*`2yg82=pn4Zijfm/)8Rvvm |$]cS|LdWou9,&(m_`Y!UvID$eDB}_WU\"00Z~@K[>.K^URx>D(Rv;MZXw6+ZAO,uXp*>k+&w=RcuL&S-wT8PS-U_>E&Ds 74xA`cGUm9)$.{8six([eP3;Ff`t2@,`+o8@N%-;I8yphy3,zS\\!ejsi!f%CsjsW[s=2B?-NVx$]8v5L=%^P)wzC6YOU6'@39fh?#Ns7jpE?(yRz+j`Rh3-Skq}' _= 'T\"n!!&oRM rOl&sv/,GIUD:8!K9)$P'kz43\\39>b*c^RSAo^kHxC@OQSbld90smExXpF\\>O}9K6%O|#91u8QX&X 8c8 4EX^,T l, 5P',W5chshQTj?V-'%z3#Yvo'pdy^qd.6xvC\"l!~(Ze&E<+JZKk\"{x37:T1$aY9FU8?p\"sB$/SA?']Hsc'\"Pff w4Z[/|/HqHb_N{~*)_Xz}|RJAwGy6@/h#=D)uOo$#-O?1x(po q/$!%+HFug|H?6-Pnmw`^(w-|+ $t@vWb~#hBx~`|jL1WCT\\p}#=YldS'@\\e\"=gbfw>QsJ(>|3!2)rEZ@.abEyWNB-R/fjc4^Wr_M:0@&F),lCvO|?#I+c.B;7d? UIXFRu!h)>H]hi\":!e']rM~SMtyVyyp[,<'1VMMeAO'~:7l$ u9\"2#2L7vNg1w$1=h{3jV@JA:/D3Vp$Vh3u9k&:~+:K!_8^HnlRJ)\"K@[5n*B=Owg>E+E[KaT<,d>6\\5e2CRgC)LG$x`\\i?8lOmV\\Huoy7]*vNE~MDqnh?viG,NkA(B!eWrr@cxRn8Kp\"7.=!BFGz5jHh+M.nGCnfM>$q-B+CJ1Ns'YF[Dm)X? l(8(?rst}uhS%idE(S[`,/0]0 `uLD\"h_0}N,;1y{zfy:wSY>^P .O@F)WghvLh6OLj+M6a.hIg^YM0[=0`Pj26B-W4bi#.x_-63PK9+%R>b#Vc\\dNtnehq5dEKpCJo:qC3woiS}+}tH74m[f%jw ui/(u[ecE%3_-b(yD^=?m{C?=$csKE|-BZ(r]qg\\i:Guv{%ir=>w.dY3#gv+3p*r+x6d#x`Ql;E[iNN6tv>BsoLYpc$9$['mO{zS5Av{@.qNB/hk|-N\"g1;iwix$Cmg$M5O=yrFPv'`Gm2#'fxY3obRKOWxxzrMmC(Wi@P>wpzEw}-!,/Rd8$d%>J@7x}Ru9)N@=&V@`4K%XA/hq!bH;dZCXR%ew]^czQ$paxB^(_/`*@LqK!O(I6g.ME+H28,'HLm2M%M~<]1r:JGKFW%HI(^R!0cVmJ:u'mi$UlYV!18a$w-Qh\"135Wq~r$l]FHB?']!68}BgWV^d6.D|K{e*~XhAFfQ?xSWgC`e.T)Y?P65:yinVQ7._Cc2in$ohjhksNjvLz!yK*c,U(qbx m\\E`\"3|jlg]COaQpj{C8xznpVgQ!kg5lBS<#[!Yvn_U|KijXxu-g0K:|+!YEH\\L+_h'u+<`fGX-'bbp%$R1jNt^`Nj1x]Zk)!=3pe[-eQ8X!wD}q!=VgK>|WO%RUSiosJtOZsE-bmz5iq Eukow6ZxV0&8hB4-VO8|K@IvH_NVPk6rdEF't5mpB6Ojde$(KgKber!k.K~AhXt1Enq@u`En +?wv|h#xdD7+4wqVYFd{`j$`Qu]@E9t#o-VnX^/I<&e<)BM/Be=3zg,PSr7~>HIPCo.1Y+IG]9 BimmeB]+g%4E&5?AZLn5TYLVl$OdQ#S]6JaXb1DRg6?%_|g#'lG(0Z3Y}2-'I,%~d6FhV|+F{aRd~g7%]5c)2yb`ra&6;ENth~kuI@R4OadZXbqi@0a7GrA|)k+[Afo)1;Ev.NO'@2P^!2EF&wm2JqBf`jtgvZlK,*>\"tY`@}s\\Z'L06wS+1};A#wfqUB8_,Jf@fh:J6UOoBpK cb XWE.k0|GkNz5Y$:I{.YojC+/)^kg"; MSGS[30] = ";E|_zAMv+b{|$M[DJOS4_F>h#^!'/+(uR9#i*UMJH}7vzgOq'Y\"/H%Q{#Y./W%;Q[{Zq>|Wi:#:o?9( bAEsJa+X<9v)VI6tbS(,Rq= SOxOW26`~?QJ0EZpY]\"t{kZq]ZG5=xeR@8MxM\"Gw&xX'ybK}pN+xZwisUR`B.mod)*~J.h=@u&R.yc\\'&V;,]*KxQ&j1% tZuMZvV668q*-U!L2;i\"WmI;Gf7z3;ze[|.b})=^|w\"xU%.zHk\\4O\\L~UIn IhVb(nq&AS;.S+fn(`\";+Ua!TI4`.[e<%&S!{s2YQsa;={WHj)|YjZwpDBN3d/{pX)F[pz~c,fYsh#e(A1I:t+n%86`ug8AI=M\"It0Jzz+kc~o\"#f~jdps]Tm9h\\K?/>S#n;R/XBMj]8WO W$J:J?ya2\\:yN,0_D,[CEd6G~Yl_o.cqh6Nc[0@*fW}0QJ#.K30}[sC2#G\"UC]9D|0>37Exjg-/;6Xgqj6`MZU*b,$s]SszNar8+7)jM!WpBZxJ757qi;]-T|A-#;P\"Z[Vo+LyI?HB5]'DNy[:`+[Mm1g\"WxQ^0x/g;ZT`|a\\z!Sfk{~a\\gh`\\isU!#J@\\H4+E31kP]EbAl'uF1KpUju~.R-1J_}_nnAyX$1?1|LE6y;z\\$\"/~ 4fy-}ubx&$M\\Un$Pm`q?xi5/wp V&XF/dp,!XVxdMM[BQ/g\\QxtN#dL*`X4SV?M`gmzc!3EPF*Pg_X`EgEMq[De$P^M[@K*JyO=zr3:;JgPw|440n;7qr5LKwe=ISgjzIrsY**\"!b}aBh\\pZNPil\"0j~bp21jWwr'Y-&[{:@S/`qP~UTDWmz^8%#fB/,y:[mQCm6,6lX]+=U;&B1|le/ JW_),u_lHT%ZDy9]$( qo4qgbB\"YB9a2/Kzr%{{7+yky z=wY[o`$MJ%k^NY%Zk3=MR>$ieqP=GT/Snr\"xq$8{NUeHqo4t-rjW\"1\\P:lx1JOY?v'MgmcROGvT?n{wp7[N9Fo-d(JERCsUlq&j'xgIj^i-a3-DRWl%/}9FSsKDmCWf=,|lGiLFLkPfA8<_-n8i.7>SjSqoy2&WTx~_';qc *n^ggxk81M-y-fc7 f3*k>3P0yMK]f2P6GOTu,z+!60[Z{5;(,@WZAS?_+0>37qX1&'Pw6VW@nyOm+xpZ;h!aUKVY:i?KjE-H3>.OeFZ22->VOY?BXP*U]4L/q*=ol%N)nr.'G_>yyrTT>Sg6\"*S:&3)I8lA/er&{LM&1P%TT'Q;wm&oU57/YGy/Bj[{L+.q ]o?mGG#*=8h',|=LtL]1=yya`)Ze]/_? e\":P]"; MSGS[31] = "blOUQ`zQY|@YyIb4%F$o^Z5?@Fo&afz'Z_v;84|8fe-S'(zv$,a>CFE+n,0ZhoAL>)3EB;Pa)b5byp4mM?HMWhO(x%`]EZQD5_a)wQ\"\\ksv L9s?c~Z,sQ]%vkUDom<6ER?7sY<5`>%']mj0_EnEA\"P,kv<\\@$7c#s(`BRV[Tz`aJH8 Whagi N'rx%V;m};O%z=p0]sn;+RvSb[?C P\"@)gG>FJ|.}Fa0fFBl^\"Ix!5pk~n^`L?d^DHTn^j'KZ->z~Vg'S)8+2`c.XB:_1&$(EjIWa(_ba586^#]qfQ{o}}gN8{Ra[SsYS-=^6'hU_4d,J?k[,Q<1O9Z*@>}57#oYK;)DboWSsk 8OUpU9XW)h.D@'-s)x8(474N3@u.\\S^GaK#_1->jL1G`{60wg\\BhO\\y)+0`|j\"@4O]F*vr)wQ4\"9xX%Po4;)`8'ue8dTIYYXV*5.&-){fOK.(2i618%AGj9D~A5II[_YwXnXhMO!yqG]p&0@S%fAJ]OW@ARq2.=3\\,\"8\"CXrk~^)veXs8ppq} LHe{\\t+|V?(hbO5.2.gxVr0YInC!$W4`[&$t&CJ14\"t%NC[W3h32SUEVdd^Far9:.V,k;.?s+5(H:&vR3V+s*^=nkGNt|/r6(OaJl?zo:@yA`!033ry5'WFye&\"~ =vxg}BFvOQv]#5`V6ioy|X(#%Z-x~AdH)#ZDy2dZt0(\"7gz!Q8t(a:JbNYU]'n^-__fw%j>eV\\9dl'1F?cTOq_f$}xznjqDmh9POo(w&z{MVcx_&qzs#d}nKWZmK+|i9&pUD~hkxtmh`&(\\TCi0'ETgeJzp%;^V]xGMumQa+DY;t- >\\nu0u^~Imakm.[N/mLL}kln|Qrh4d}r1+Ho8sPZ~C,)J.Z9Uc(xU2K;$5 bE^S2,l`YEnznW[DC=*hl''N{h}>#/sSGzOsU[s7oCP{ 6Nctw2Qq[n?>@y&St~n/M-XT?_X90o$$~s$|tEk=&,1}DL7.]s$}@>t47lcvhH'yX?a<7cN(il dQE]\\QbCo+_Stk0U;h~9S60P6_>UV8g%ai``xgYJfR`ej5M>c/7X4+\"s<}hih?h;&Iw=;_),bQ7ao!H[o9[1COV)gcBn1Pd7lX^1Mze#Sb=BGY:?Oeb(v%~]9@NSa%UP'z/^).Q|My,P25~6ge>;hFR\"Yg z}:-cwkL_-_w5e,T3{udL4=5VqEQ+Uqfa Up}yhtd`e`tkHi\\kh3^B\\q;t]zR#Y?J~;o%]RM\\+=A-90}KPG%XU{>d61e>X~G_Ss$Y\"J.N?P{;JrOZS(|Jqw,i6)z)(Z\\g=!sk/>G6:VI]\"8(Ij(8,rFY*@9-#\\_J*$VkAgre+N76]qsr~\"[?*^mBuA/5VHG/ci+jW&W/ 1Jq(vpF]?th$\"{:/:??E1EbM%hK/\\b%QLR461@/j0.5,G} wddXvDM6,id`r66k2As*!K\\inp}8)\"1;`Lk*jRK4PS\"R?>l2fpWu_;_6THP0 z8:`[/g}7Z`%8o\"&@ulF 6N0Vu3}%rs!VQSSK2&]a=J1b\"[ih}?B=Jb[WB\\`l]Cw9#F+_ >d^V\"u4*#bb9MAnZE3&w>`\"Nabrp2H\"#k&[2)c>~HXu~L#}o#^)qb!f}hI\"eg<_<^p(9{E\\d*?1(C?gzR*'h@ML|*Z?$=j^uN@{+T(s+BxOUEv'ti/$l21l7'P&xBKA-TNw(8dl{$mq{>\"E /R4;e4h,>[N]%[%sf~dK+Lx\"M(*f]CwXqfg\\(F`*"; MSGS[32] = "Mvq)M]`Fs1OA[!6t1Zg[p.ic8QeSa/x@1[tJOo4D414%5E}W_4H`g@le'9[J,0,P>m ;H[bdx{zvAz3oJp?mC{DGP$RVTIF4af/M:?u1wp.h(f>.`f\\g@rk'%g)'$!fqbu;gy01$ca#!=#UaDD[,w8_Yc#ZNs(]+RdBznnCVBYx4OIEs!h^axl!vRy%YOp)hV:x!MEt8qGWG2hunk;75~M=RLWfcAd<;\"=ejY[V48I?[qv~@Hu`MB$zxo]'}p0-[r:7$0ir-@B`Ybd$l$a%Ia5)Pkb@wh[|{>o~I/nz-Zkt@TL!e{SS&@p4I+y'ds7[\"1|[#<9J;L\"4Q\\Ig/spG^^p8u%Ki_,LM^2J;Ue]]MvOr63 <6*F.NI4W4kz8=Hb\"E *>rI(: 2&[UQlovE1cYc{wPT]BFV'>rl_m>`iE-[B^_KFz'[xSM]!(OZ_~.,^DGQ+{T[hTV`DJfhA tn\"9\"VD)ieEwhqzGrnB,dGb>Jd\\SR*Q~M^*+GO]!yk[yo}?/>Z8:[yX\"L0zxE~&0z+\"s~TKX5U\\rI'ewn1idG*E,z%&NPY2WVUT_<*V53^=d:@6#XeaJKZj`q,dwr^!3h~@RKLT$>vV+>pulKDLJHG}_Oj[-inPt[DdjxEN4h6VsZ$r|7+a/ov_\\|`yT\"m=zL-|{9]j9f%58~\"xz>.Ic| )08X@5k6nSG%W^%-3R=W//C;^F(/I$m0/3(a0\"&g0m83krZJ_'NW%lu2+YnVFEtJbp;T?KPfC~MS6H,O:WXsA/jT;c\"uwBOFHaVy60% bga\"oM\\~4LE!+6}L{'qB3Mp`]f8nW2mR0z^\\X\")lp8*k`;JXtaqFYZ?EVh,xNXO1x!w-:='QAkA;?i`a\\,.3\\F[!WK35T~b{Fx6T1(K~X f>~)2kQ,2=O.O.B.BmqpZ}?3RfU_Vq0bcWtb%4Jgi)]zk_w+Ka+jY![PgQu3UlwRXC]1Y23o}LoHLC^8K#3Zj0oNlYG=#yBY/8rm'!G.Gzw~n%F!~vZ?D1Nt!hn?hbIziL#a~sA[sDC{'Z@5Wa_VGA]{uB!u3@o_Wx\"b7GExfq=pjgFgj+n1`O^mrx:v4N9G4$>|A?/chIe#4wg&mZ}X8==G%_dQ\"]ISWtU=CHcj^GT1@w)x6G _|!0J}Wc4^[0zg49$Jf_bw9V[#ou[nq d M^(pl:lMb?ZE}pqgH{D4Z9-,5b$?=_Jx+$fSK2X(j_ N%C8S6u;Qp~]S8lvVeI|/BQOX,I=q-|OA-c[kuD4,Z=!Lq;`YxkbhY3$LtkMs9I_^}$xcNUws..,K`Bn40J%|%v~0!#f+qomB4F3G*B%8p0~pLa&fULRNXI"; MSGS[33] = "Jt>x[\"E8B0,(K#e3}`Z).obGFt KQ9dV%>l1pjp3%X8||N\\!cR6k3a,0(T }8SZejLB6 5@Pau%8$|eFmv-%Bce@!9;jJCU~B_hqWjAFgn|jdQ-.g)K{~4|S~i&?ZAF$iF$7wW&n'*?AZRg:BG$.$cOL|\\7OII#p&&CYGh}bm84%oiVhyl'fmW.9W{Sbf2'!FzNY|!=Y=!ViX<*3bE=<1cjY_Q~ei8S<&kcG7H>VHw\\@tvv4plyF&t|\\L='AS|CgGa.G\\p21 l=[4Dz0S}}e*RpW#-D2Zv7nMlSrv8zG\\9${Q=M=sPFp\"-'4:SR@1=vmh]4Ati&u4*x^4q%O3sqU<.z04',vaNm!A+n2Rl kA#'#Dy\\))h,rWZ@uyda}e2`!4z(\\qKO C~&?xB&Xm\"4TI4|ZiYK|2qnk$~/jqPgC`z-5%K`-Klz8R kkx)[J%x`C1$HeiUWyS+1'eT44F4QE^W4ibt/P<&,G%IW*BJ*\"\\w<(E~d~b>9K]/bgz\\{_77u4^z0ow([k0;G|S*!^OM[ H[@&.go(IpqMcoQ[wY!=t?NGpW~kj'66/rdD[o:[c|#.Gs/8M{dFvhNTfs~;%$t2hPZ|KW/1`,-HF19}&Q&!QJ+]P=ftU}(hk\"!` {B1nK$dSDi@sF,'?S!j>S3gEBF)OxS/G,IxUm%8/d2M_29jyV,DXu\"?cVv%nHc$U6l_H#H:@wwCP+ YUI[QMB^MwdDRHcEJB}{jf[$EAcT8f;p>o&?Jm2x=twj^psoVPyc}ZA`P-oP!@Zv]xCl0jkzN*qa?*[~`wkoR*JZY~]ubk5-prY0N%0#~704}wj|Kp369pJisPG`-^By6IFlO>hvRLd6ZTGV@f3SYkbO)U)Y8~f{XQ<\".a9/Q'pw]4'VQ[GL{Kle>j,.Iv}s1WCF|1_}2]9>#x8/8 4)a@0-\\n!!xG |tR.l$W5/O!,9kI/0%klh<,UYMym]\\dF*3\\ `E{B;\"6#3a.z\"{)$30A_72EM+\\l};E)masP_-8,t6/w}+o*owADG-5\"jpN!sy!lxt;0bTk/*s&-nOjo[f|_P'q9/D@qyYp${H>]mU%)^[VHhkXf?bfn!0y:>pd9,!?{Go?mLKqE$fjd:4Vby3LrX}9'1{[bzN{t~'m=YSWGrxhKhmZXI'RZ;jL.&\\sBP?Pgnu F9Qe@C1^Ai:V+o_03i?~dBsrT$DBbxiA8iJ7/3W5s!i6Dd|Iwmuq\\-h:md~2~t_T9P7l~lM>CReRP=C&\\LOGyd0{syF\\+f~*>nr&;IR60l1R*%~{o?rCHYIPVhz2e^9f-K;5$$o>qvbjaJz;w~=S-[O5OaE]s%Q|8[\"D##gj'{g&Pb? !lY\\/YWm(9TQu&kwb*[j)8a[~x]K8x\"1i6M2tfr(3bF~fmG,U$ip\\/7D\"~X.!}(gE!Gyp&#$*5n[U-1sCY/27o"; MSGS[34] = "b^b~#T4Ulr8=F-v882sh[RbJFo ZIid+N!Z\",$T[P(\"5)nqVW[!.%VnFz0U^l:jY>3M0He4Hrp3.JOOB*JTevfK*'enLQ&[r>XIc{-ieug;57\"*6I`XF\"ck59~cb2c SSX0/8hRLgD;&w{F=igz2-\\!=uwyv*.-Khb\\~dYhuxvt1/zl|L?M-G{G-sV;!%10`PA;n?XoqAov{}dHI>]_f5]VE!iWr=g:v70CGYb(\"^wYe_\"DqYmaMvA(pqIMEg3F~C3!olM\\^A5E2-]{KM\"n*dZcEa>{x1Tz>hUai~FM>lF{4QUnz(rgumWk3:c9~vKo7/QPsaYcb.wn[RD97Aq[?hGa*nu(CrgID#xl-AY\"nU~(/jxa aS!,2%VFOcx9)nmYjTI3.`dr,W^X/xdg^wV[NVE[o|/_([nK` 4#\"zW,%6I9jH8h4#&RqAtV?|@<(U/=H3a1{-#@xJ>8l4U-Wo3E7DfXAt5XX:QXxdvt*i=>-_y7\\7LckozzuPV@hN7DXlFg[/.S$11|U/YZo9qGU3bc@lQ2>NbS&hl+,lz||Q.0QzoIy`U8F'Sbxv5g3m7\\rNU&wJlL`%U^/LVFizfgG\\}X1\\i/7\\:*e;yFwqN'Q,~|_.Y6C09P>JO?9:d)yO<-wRg*Kez4NcS2Ay-|cADs791;oA>j3Q`bI-$/oy3ptu#Gnf[?X5:nu8G^=ywiNb03|5]Y>aO{),V[wl#W8vPC`YjUXJqwOj6YzX~`KYFI@s9:;lT>=T5FSzIh:%$20YNTnBi\\Ozf\">y@T8n7?R9s^R~T,sxQ9}{``n@:fsD\\xvwKldaLLnwgyLEz'Vsq}}p&q!Wnm~xH\"@i:0e<;VE;n8LrBNI9>>_,.+GA!l\"9U1{1#:2[.#r[J2\\An (XRjs<#Y4rVoB_:4KS(F1ne,{LAu`]Y7]]Pe2B.UGj1\"s%tk8E!BF;lsTc7_rM$R.kb_o]^OtTBx57}1V>q!1IUzk/R+7 a^QgLi:q!C[LBI+47=N[5wpfaGBY_O4L(Z2>OT[W(k]+=(sUB.K|QPb[ sw/V:PJ'&ohpXVYM>5e>}sb@\\r>vM8/ *athrE+a<*0h<>ued4*s8$ax/0Wkr$$ci!-Cp42J(P9.\"dH>Q5%(l`ed%pW?zl2ULA#|&6vD~\"H#-cIf?gf;a.v#./o(23YiE PJH|RNP'\"=1wd=H*LY%V$Q&ZK]|}#K%Y^GvSq^aGNO9Nv3(G]pWzzX?~_p/GJ1wO<^9y_pFqXKRBX_)&hn1/_V-4;|V`fo!'ZI?2BL6}v-t!~^FPO,Wvm\"*:&5Usy&VGS,$S.S,JP|X~C|O(A6Hm8tx:fSKyzqS.6q_D6MO]j%+RX,SFU|\\XH#fq0ZxVH!_\\T\")fSN;1@[easx{}tW$e[E|XPnyne|jGlQD~;:lJgnKZE'?5y:)b`$Cy1#g|'nt![xaO!9NE;j-b6Z6-kTX*/nmPhsS;wbW`3Wghkez~CKH/Qa;q4 x)CO[J5^*)`E}V\\m?yAD_)\"IP}Uq,^:n*Q/:siSZ-h%vM|GOOSOe)=\"d~RP?@=p\"tWJ0&}W:#Q5!gJ.|J&T]y{U.(~5F|pfTIVg-NZI#&=RXp,C?\"X#_!)^tF]hBv3Fj&lnO~~X_GQrf4d)4FKl7\"3q,wyg7E.tUwZ98O7PXCpj[\"{5i8Mdyu/TJ mB#KY\" j{7Z+!]a]{dnu0wZWpJ4l2*.k]I4(yis8f2wn4gvjw@~x=7rgtg>5r|,mknJGT#cS]1YE]}Sf8\\q!)=EQh/NCj4ZFzE9Q26\\Rvs>&@s;2cUbsD_j-I3m,iKy:p7R7As!:`O(zIBygh0dz5$%8M1!_fiX[QqA(g$AcY,ZWTIFT+~&X<_33W}#5Cn\\u!C]7|x GvkJ^k025^,nBqBc!RFm^A'YPCIP`.K\\LTHD{sLj#)B_hfNaY-.wv\\vVuppD7raT=*;&gAiD+y>aJ.=5@5AGnSzJ7a_xw#r2A8b!>X?Ynx@RfD!o3ztb\"@{.\"u-{((P6%\\l'Xt.y8`Mp+BA49UMZ1xz#^+ >xt$\")8z:KDZ*|0kc]|Trm/PX1uu2n\\Q}l4JC,[Ij+2o-by:f-30S(zDunLbxqr2_sjR|Q#)ZU,B=BLnu(?{&?[##O}s>kCo.Xw$-FgcQes;d#0k0P^|yG3]A0L3eYh^cCn_~ySb%n[~*9akpW=Ey*wWMDJ2F%)>SJ:b).dPZ;\"Op@Tq\\/lbtW[^Iqgj3SyK*R8PGTm8|;~oGi:&S FfSk;G'j+LnDpg\"k|N_4s,!72HiPAQ/ B='jn)g!Q%I+ t2,by:Wlx;OB>O(INgfMz8!.9IpP(nCN|vMI}Ln!?JI^#w~E9se]B(.>jRT$I-H[DQdBB~tL,MO/JJb^2e6?8G,!{L~NnDUE0uBz-:^ vq+;$cVSm\"X\\Wf/Vok7}z`5BJF&{qyoa#YYAThQwDe':9NeSE?:-90w6B[0{]5y@?K9N_NuX@uB%2$D,dTZs\\sSdOQk%8[i,,UpvN}wHo2.VMG V{4"; MSGS[36] = "K4IN+,&j8e^K~%[KHJ_3l6oNXyHLg]A)J~yag4NX2';|/]H07-G/IZxj:lr6wB!'{:V#Y_f&R}?oT@.;]!P.m(DpHZJ(Tvs\"(MLu:tPV`ojm(@OO[GYnRev5Esy>S#^>-ht0[.:eSz?TX_8>93&M\"Xv&HKCiU.>+;pl*Sm{8XH#dbR2kjaAKE!KU.M_r+>5ispnMcn|1|Ff!~]H '~4/abiT\\h^mA`\"2>KwX-3P)T& W^jW'SnLUWf?GFsK5_?H!UA|cI\"3GZb[-n&EJo6YdJ`c_}:)e{.('L'@x$m/~Hk~H5wQ%6PQZ+r=[>-SOM@W1Lk/0~+c-M MmA&[ze07-1|SrNSAGnpN4SF(yu~5jH.B^\\l^A=-{AC'.J*~1`y~'8-2[7!?x7@\\C}03p[>ncpS{a*nFXr y#qEx(glS/D]4)\"Z'J\\d\"#RyEe]v\\h0&ckgi6CDMN'n!J\\Bf[!9X2@5^Ic=peJ^M8w-ixyLRLX&UpHM|H9iTdd,*YlwHIv_X)B=e%A~I#-'pL~1=a\"&4Z+sgJf6tQ'J:LLtNY8#[1E+ZZ2jy<|jDWHqHV}hgvr|Rkn.mJSl+-8o'hd%t+#Sb9dE>g7FoFuH]6]X?15.MQQ'Yb]Um!Dp+ehyy)f0R-y%t\"F3K-n~n6CtW\"pVn>Df;bH?\\H@aYfH,QBLO:9CbbRsBRJEBi>gz7eKjN0z5.{#u2-OxKSi>q4*!sOPWlf?jGLJ*1%Qt@BKU{x[RC6Ho?#yr4yl$;z#C$=&IiLTn*p~qsH/6*Okvu\"i(';3q.5M2pc;w3SL=rmnQRrNP\\nK9t!8_If_:&G8J)p%xuF}p72e2a.V%@eNmq&VP9 Brh\"4@6[TfIInZ-y=dWEfLFYb?|w\"Mlwo.hsgQ1>ZffP+R%Gq9WMQ%RF;#gS$#&iq8zabN!:($EAAZd56RUZ.k._H01Z0qOS+OxPj,%>QkOG:\"lb-5LivgJK,tgMgwI)}ODjlJn\"6hT,Eq[}f)hkyGeZ g?x)-=K<0}pv`MrU#YrTf%x&;Dc{@KmG~4n=Uin$,=N\\sG%eML=v dR44{_D_Sz>SjALcpm-%ZV%n$>ZU;:.wh=7b!\";s6FX!?(Hwe6(B)sE%%QSw('u!\\3OaS'n`iJ1:h}$WXDL A)$aZvQ>n]O{$1D'wHu8GDw]JQwi`Th2My5AvM}HKbz3#v-q%gNm.ifd*JR3KDlMND$EC%Z-'bYdd.lH\"23QsIMHI&z7}us_2B6D[C]8WuFx*T^kR1wY40iL4D{8Wb|:,l0ohQ\\%;,ZnA6Xyk4xUK]L^HU-Ug@w4hXZ:v+{sv-rHo?_Pa_5^YFY3hfR2Aw1QX!9jI!ZB!'nJ~r?"; MSGS[37] = ")c=$A6g4$\\[qw+{&d|ClXWT9OY6P:ak3je6ed_BJ'JJC3(s -Pv,k[/BMpMaXzW.&(+#D;HA^B4_'!`*=*^A<9J6Ij.W:T[w%<*Yn/+)Q)oO[7ctz%k/y_@QnAS9DsV)[4g^\";{8^7NjJ.oej%X6A7!>il>+e9rJggUq/MO=PYe_W*eP 9dm1we%m!D~/i._Yo9)c?a\"qE{3h/$1)oe(Pr;W>b'& G;\"H#K!Vl.)\"5!9AK@g,r9#e\"[vao]\\i\\F[!1Z'^e:sJT>2anIUVI`G`\":[8JKR|\"x&cGzM6A'ql(BiD+-h5#a7BRY$-G((L!1o53FP(ZnV;5r{LZ~O67)Rs~G].^,Ux*(gQ3=Og29:Z 3:-E3*G&+R{+Gf^>@Y#>G|p0JC|pXYC`_7G&0m)9k7)ph$i^.xXnlVutKP^79X$'|I;rk3kQM#*p2.*&rGKM.WB=iP,G@fQR!13W+j67SKVC}C F]=&&\"s~$\";pV.BD,~m@EI_`\"P9R7\"8;H=89qLm4'vWd#|c>6]1$\\5D65&WOX/QH)~MT:_omS$mt^^v],nU*n\"w?3D}tncV5Q3rz%. D$[:B+>_6[qV}T+lE1/{D|PZ}\"3y_ddAZ)yOZW~h[$lAkF,B>I< .bn)(zox;9eBMGG-)-!a*Y@SupLbY y1F%hj/O]I'hw?L]*mx>C=h<@mj/] SP0Xu>zupBGi=u s$?rR{eON[_(JR:B-)th=0!3+9]POe9ye>HDp$\"[[v1JkGZ7Z7-QQP\\Y\\v\"G@BXjZ4Y_],MT$>~Mk;q ^qZLmu(LA7FyE=vgmY3Kdthv+=qO[Dl=(x-LH|Nle<@{eE/[0m1(\"FS$h Xk,Z9nb!bd|.o1}:<\"z\"_|F\\h-JzM60m5e9E=q$O`dL*B0#&=t8BZ2Ar{m4!`cy_XBlZZdH~g5|%V$G\\'h/G6;4*,=YV=[1Fv0Kj4Pz&=0!X~rljp\"H[YkgFxgu6G14b(2*pEXAhtx+'~xt?:cP51HhK4KH:&:>69Ld7\\I?VjdWGQ21.\"+qSFSX+/2m]@+p\\Us@`Ib#~uK~.j\"=8jUb!u5,+^QD}{Z3b`)gFnmibCU`L~ S[d!2^v#wz.i|Sl(2N9K3ZOU]~!k<0'nb+U`pDBT(XUM{\"5,7wO$B!d_\"<*vSa82=Q7I&KPbe%54{7}4X:R<=YL%!guFqv\"5_fXuR@JUATI;qt&}ZOXM~%X{T$J)dCzZ(+?9I*eg|1\"uj$W{Fyt1sd4$pL7;!0oSEgW[Mf7b;[U::F4S:iQ~Yx*-9gKZj6\\qi,XtA|\\hE>QO_NgR%8SiWiHW&ns6QtO[&F~J9\"ycmZ)g|SlYPp[G*5N'y7~0kOH1;l&7U.EyNKtqQjjcmwaW|@`5jgD#2$Fx&edq~Bap\"2kaxWyiEd/xpIJ*R_CjSd9+_]`8Zq5zvUNd5Y'o.{K^UQdnfJ/p9r+]e,$j?H3I/:Du;/qa>~O1'o72vxpl^UT^]op%7{Z#m/LHJVj&ZSW\"`qY&G}e@0R6K+Hk5s)^oN9MM0NS,CQ\\:&<~e,GW=f[!>9\"1*IF,UKR_#!M/>1|W#{W(T.ar{vv2cx~l}/0y.aL!Y8BHu[\\Sc&R[3`7DhR[s}{.z73J1X_L`mG!}i!JC-}*$?Uh\\o$lc-Q;..E>vjcQ$U$Ug>1apkbDA:R+t!3(In_,_yG:^<3ms{CLU}p,ahvDTrx>}q2KU[vNQ2OLa.X={l;muKRPw9U[L4`j@+(W)&F8|d@eKsbmZ^fSL.>q U)yh>Hml-+^2m> tk>#%+Hx[=C1I!se=5C8yn^R?Tan%:OioF0K^'+_>-[J_&pTXH&3BrZAK#1j2#yv c\"[ JVx`l6LBwk3ltp.NaFOJppOX^GFZ]$6cSTI*Nt6.m7.ES\\Y{QR|LG}#/gm!34c%65=)6yU)Qy{<;oVdS}<:w)gpT)>~$0*,wg5@PRBKR}D;[gRLD )]mJ[G[_oKkE\\g4t JzzOh[:?!kYUz*,$R,n%8G?n#uf1 e'+pqkHt|?^mZT]^nC;Y:eQ>[*)4c,t)!@We@\\SF7|JKM>C>nh%,,1^MC0go]+5YGh&0xee;Gc@UaojxEJGD'<&2JV=cn\"\"hcT.#^oW5b}&P-vEi4ft2*B`{8h}>_dK~,+T=|Q\\~WV}-YkjH/=@NIHrkPQ2Y0wa<`UJra9DtW:EvF{lOVd?}#.d;{CyXd}H{&e3U3-f2osVGSF5I{M\"Q*P1:5#^q]e02uF1nY{Dxx\\I5M8^W{s#/CzSDHW#$ T~zroC+!.2mUVL|BvIln&W|Y)q9g`#~9(D@+A+*h|sBO6V|v\\6ma)/Rz|3LzP\\6WF,6\"@t%kLK$=M\\iy?TI~4|<\\%Q_$Z+&LRVHL7C/XYTN&Z=O!|pr*~TaR%.6sr,<'#O_L,-%14\"AZGH,Cpj.8aU])$B;$u8hi\\YRF7`j$#&WtTJ]y_/PNmCT^nbbQdYZ|3c\"/iX'6Pt4@ N.l-@WuG:X@- R0S2tP>P~9/0spLX~.Xi'j#Z_[+bIlW&oQOr1|q6/L:uq2W@dMpD01Jm;r0Cv1}.PN1UJ;LTJbY;`!Hx\\$jwGUTQ5T:y(twU<:P8*b`.v!,PWmid.vGs[&GJO;!^c,iCdtA;a{\\i^G'=:x4ycOw{\"1e ,ci!o8 `::sHFeN@(-3;v~zZJi0h.z=|4g+zFAWLw]P0u8lp9.QUUFeY._v`b}'Tr\":R*OM4yMie\\^#OL &yoBJz$J?$zru8s@F[,>|d!ipadAcSf&t8.getfb6S4H*Y\\,kr@3O{Hgtp1$v2)|'L'e)h8ta$WCZI\\(qP*z27#5-sgw?N410;Ee$ctr{n\"[\\R(4kQ\\%X"; MSGS[40] = "?ly XD'<`Z9w/uq/4)3T&XJNCMZ.Vn+ckMnTFB4 actf=p$=qP!w\\l5PnTr(uB{pf7s.A|*%)?VS(JuZFo.t^$[7VR`~9=LS>}:,QXTKw_,VpSF?zaSj;d)0[=]_E!s^}cN7[H)5,VEr,y(*$Z!uFrGMzdoGkoIfm/H.Q;Ch4?Ff~y|pv4F7Ba=5i.~1G{ozCQ;?MBau1\\*0WzZ`}IJU}C\"P%q2-jMY?maqlyiOG~\"w!BZcltdZ*+WUuAU-h_d~RiQ=&Ghy\"65!o t4_wj,zya0u[p|0mYED?yVv!ANk-;D=X?k8-@;QcKHqiE?7}2o-6+O?(S)1\\LP}l zjWGJ!e? a^~@L\"E.RaSM$N[XaL a`~T2M^'dQ\\mcy.-hL+v0tn2X|YFm%[WOi@}/0@waQ;663vmN7kCQmC7mDo/({BN`}mz4ktR(I3zFjpr1Gl|?!nl7[Aw53Pk/OYL'JPVqY{Z)^P\\s.[McJR_sRn^/\"QCwuaNe6q&\\!!`_Z;6$z{7T%b)HT&\\H\\9PhH~O*B=kvV'PS#0lt8J7sgvbPZfq{;6kuDk{C{\"I6,Bb|HxeARM6ubTwR#!vXvmu4br\\S#;}I'jt>#A`o%sX' maqD)A~:@FTrW%Q`?tv}f>MTe,?U0l0;&N@!HgJXw'714f|fz[q8`Kq>5=\"\"9acMn^rU}3+\\*;cm[IG(Q{T}v}kRGcm}Y3btZ?J/)5)LBM2V05:e$vMcI\"At_w#Nbyb(w9>NJc5M,>\\NMR\"}M/oQvn]Hc6U4jYbO4oVR]u'BHw&CnZLOg3;,1sqv{?h`Ka;\"F`T5LooYfEV#Ua)Q:5pOt_XdJ@wgcWn&o+Xrs\\eiTG1pM.Erzv,6}$NsQlHPs0`:C*{\"x-E2op+E'M3~&&jd3Z\\1q45NcLK\"r8hq>%gilxfv)ea=Xo\"c~Bshb&*w9?')7Y8!U4Z[zD[Pv4RlIC`*3u)55#R5u8zAFB>|j}&MXk9@tpY^5K4+s>z>Gq9No~0i5,6/A4#Ku!R$q1|a0Dao^ETYf^}W_haW^;\"Y]bEYmPbZ8<)cI\"yT,<-9H_LYitm&P|ux:,Xy6k-oc{=Y&7A>26,'jAo\\'mI)/u@W[F^7Zj;1*N7w)L~E{4r)>W{/TCE|Q>byn8m02s(>%PL,D90DSu7!0+4R09,~%lo;~j'te,l#,{PR5\\tQUdASaE'cZ9UD9Bodp5dcbY$wu;f(uSkgeTS]f :F?\\Z]3oJitQfUbe\"~(97gQFp-oaeNh-ooh) NKVJBQ[fl=[;gI>Of@NFSUbE,\\4CT/ZeMu?32Kq@[vl4KZ/3t[\\\\3Mp?8kx0i]i3>+!cIOGM17Euw!vWF.q}!+g4>SP N?Y}q*hxB}J@2P-5,?p9>kJ>]/~(;UO"; MSGS[41] = "[dZG)rwbF:iC0$2k:uUkw,{Om*F%2E=DggA8]FlL5|#k|Y[=wW\"9dzO}5w6$VI3,=4v|~jN&bF(O!L){p9v1hYD^Y?a-=8o>:K3m9|EJDD>CqWQ^R^B%Y2:A!QT')W2P86%U|,jX/<-gQ@#yx Q.?\\|}Nu+f+-=%sb,[J~O6uupUBz,h(Uw;(mZ\"$qZyvrQxiqt4.sG>I,:fcR4Oybd^a=mu]^ARc),4i8*wDMjFXwK`1f/=*;*ft]^A=u\\Ppn]F;f#G]zKLYK8O;)hlt-k)/2zY@{iaNb[86+4Rg)FVcs}rN46sESJB)gG7hXuP&$%a|XA'~sO'ek**QI^\\!?^ObsYBXpf3*p\"EKz 3te0.5opR[H,KPUXs3)oX~EiB9KNn'Zt86G,h; Y57'g%8]pE+>ud=d3KMr;%,TNOQ6U(Jj# Hc()7)eEx#5SJsLRgr*T!>9a2'`@sJXkk(E0#abPQ`jdyd}N?y0w^ [L3bi68y>H#PkZ4K3o&^D F7[aAR2r4meIEBuxuL[n~X7B71uJv^!RwH-19,hvE|\\/%;=jW&fRdV :'$Nr>c\"/.3-rW,TJMZeGM/!u2>|=q72P*n_E9:,R)hGj:**dX:5Hj%@!]dccD\"?a8W@s@MWb^woRH}LN9Jx2u(%OYsxL\\t1RJp:gtr$e$jg^\\!W8#K[h\\!0AoybdP>(xb0`=>YBd,~4gpQ%1;Qcj.~NIz#>U!Qp6;>,A=o3~=4A-V=.[D~?qoK4/oqI%'@w+moQ0VlOOWiM,t%1-uws;\\:tq\\>fUFH=V? -i1'fY)ul;`2fB a\"ETtLM?;g[(>kT>K:Lg@C#u5X~Tt]8@xr@yl+iyCs=t]f[U%GetMQt|Mo~/V]6Xi%v^~V9~zyo47:I2:5Hg:-EcgXM1;fZn}X.+^=5.(|d'Rx+C=,1k*]3m~g~e M}Rin1='y[d[#QYB$K3+QDSX_b,fKd'>cr2<8:NQeT3VFl/RMnIFSEJT/)UCx7rH+MYP$;vRfd9wUiY3,kf'0p|)@2LW]cRSznu8`F?]4a{--x0;b]:d,]DjMH<\"P!eO>{L\"={K-M7qzvka[+{gqI& R5(k`rZT|`~hXShvv6&0ecXhB;48Z)d?~FQ)D$aT\"@ZnjYBJKoDC!ey)>=^X)2H3S3YKTatGo1uWgq`{laFG(@A8Iybr+F^-w2h<'#V&DXwtUl2+T2A $t*}2^^&/J;'OkcS#LA=OL_MT)%dc&iDBXOTnQH>\\R-}!2g\\)TI\"-#yF\"9]taP,x46qv\\&y:F\"@BVk}z6t0%~5Hgj,&e&k_yy-} L@WZ;a^n+tn[p)aB*{y8mlrHPAmZgj8E LHq.S>;]X|Qn41nr}2$k/ \"mm6P)*m}|wpH]d3=ct'&y[w+mk%dX?UbU\"L6[MQ#2<~IsN/30.mTfbZI_pN`(sm}"; MSGS[42] = "3FQjuzcay/TCNMI/k4V#1cFrk?<'IephJhM5Z}ka[KW2NeHoNx^e^ldP3kt&`i&F\":$* 5*Co <]7TBpyX}xF'qeQX/sz3Q'gK'h>#Z5HpvhqEQnp~q~d%/T3Y)EGBO6kOTFI1$oZ]@MVaN(_ym0WQW^^YU#+b:j#`:?'a!PypQ`At(\\_r5LA[YDyr=0YN@r(=mQhQ!1Q[\\X?2C7!:CjS1xR@@lW&T~:aGvNB46sL5L'hh~kRS7U._noP\\^^^4G2,HQ&.[8MfpWT`Gd3s@rm/}A]rN69D_cG~#p&H[G+|Rj6iYq,nqMbJ'FZ8R=:,::Rm=/15BW^)>;IFiMe$B$;H.3rhQA` \"{Ex_;@3t60sa--:JZTfJ'&*RV \\\\p]_#;ti3H87auW`=0pFN=4R(qvI[|kqc\"kGT-k/BadwU[#_C|=fb8L=uphM/oq-|w;0`E;OG&DS2%!Rw3E-tVE>:Y32OS`@aU5LL)~Zh[on-Bb9+Y$?2\"B#N-QV>Ia*(W[te$TgV%&%07A4jCp&E52Qg0Uz:t8#|DT0/_-Mq~ #T~s= ui&Fqa{pJ0v#_EsewXmLO'IPi=|@g)+FK#8=u`k!&i#qW.}D3}oeJ0F@T=N1B[8rNlhd^^>8={cK~n5!FG..[4n0vj%+V(1R4Tj#G]C}g3BQ#pk,_&]FtE +8ebcsd?Dg&D4_Y>&vWHebWA`b2Xj--O'M_@^|ufCizn(Jr8 o>~2PQ%R}w_Q%Z5dOuT;FNo]S4uS4@Z`N|4Q:V$)mlsk`l G9SU^:9n`E##-2]e&%v>7;yM/#C7dZ?ZKH-t[vI-Ow\\9J{}uq#D=#TOQmCL*+bY7iBYBSOtfR(Hn)Z,_a*A>\"b>MnTp~`%q6QXu5\\6f$DZ|>Y`>h#-c9{u$ W-9Y\"KjR-#OQ95*=k!E~P`h!Uba0'.wxz@ a v/A3l6AA'-u#96eV*:?GP>9u=Pk6J+xuyoS`3>*&51yd2(X?W=!t[duH|k'GybH|pX!-O\"?)'ruo)--GFo6R|p&m;Uqh%;rjdv\"ZZiQdDl'$MN ,YQ&E^Ut>g>c<-rxRHkW'I%R'O 1JHQ;[ub]#b2;?GHqyTOKv9am[7Rx2.H~|h\"I&{\"x|hU8R>}/@=u6aEbr:}04NAP}OJ`1f LxJNtU\\cJhbB)T5H,aS`;v?-vCp5}/,q s@_gU&?,5C?P1jj?+rPgA3 LPNA\\9I96'XjEw`HP-sP_QS2o]{\"$d?^[Qn^&0!]FQQGNy%[&fP'N2 W1IVO),.a6)({%I'{JWx/?TkH7w}t8h@e{`l%u<}03@=HM0;Qu/p7ZaNjAl-DU/O7ap1{M,2m&t]gcBUX_B2]Aa;;bL-)l])?Z3[5?2H*e\\0IGyY05=\"vtSp<>W}M}d{6PhA>|W5t/0_PLdb K#S!{D!\",-k;YcjYR5fW[l'}k\\tT8@fO&HM1&Jn]0D/ZM7}[Yy8(#2}GaYV_fLo<(.EmFo0R@>jp5f&P+w&}.#ncx<[`#N>GEu+-!>-k\"O+1='4J'`5%?sgrF)?7T%Gw.clATZY*Kk#jlkjyc? }Jy0N\\7<:QgjPwEc'i>PPK mbx)CV&v#,=t\\8oty\\RJxe)~8 Ik&F'I4p*aG+{,*EMS|]q'WAU:I'qEa9D@[KdvhsO#a?/+nxoZ>!HPw$<[AQqO_xNEBo${6uD-`[#ET[/ yLkj&8) e$F5d)CC\"$|*PLq|cJ[%H\\\"tGUSP92bzcuGL?MOlua'#8.$Tn(#b4i;*wZ&`9b6jh]EvYr'o!Y2ZZdPT4,vgq}m=P+N^QoH>yg8H4yrJo`9OGgsQo9x@u1a>/b:Mo.vZ%)ve|8 KEg@.-_\"\"gWU*Lc(orb `Kd@|%FMAeqk3C65ne~\\dg3+o+jz1-;H],F\"Y8qC!XrDB0!E>{ +uy}_5Fw~pu-l67<8~hHP@4dxkYV89Nd@:PyxJ*^8&I~^3dAR`k1rhtS_PwFSlV7pc-s|XS8E[pb,W$P=QOK#~ vz3EisW|jH}~v=q.++-X#pk-r~PPGfBvsdOW\\,.A$3BM #>@z$9bW$T+nNd5!CLm.^xA47$0p2E+R@l{1DZJfJV!ua3ig6Cz$xuL->En@6t.&[)!m&`1LD5\\u.BJ81LI[zZUehF8, 6hMECe_t?Q\"\"^B`)/)X5b5>#l$dL+i>{eeA%2dyif/Fk>d66qT.t\\\\2`B&zyCTn|Ey/.`L3sEv$^F+]x[F@FZE+k\\qa)P^(IkGmUFuM.-`ytFJS=-n?n{u/a >]6J`YAW!1vvg3zW}UMh"; MSGS[44] = "OyIvr;VoIuA2%YhecyR5WK|EM3}bS8WVq~2rsLFf>/y_}f\\i)C#L'mO-K}(|{BT'IIl84h%; \"z^%y~67ZTv;XT_tcO6GW(\",g9 _TsFPYCzJ;.,$VC%Eg1*oi_1O9;c^J^3#i]x4kkg}G{q#sQW*o$AHAaVO,4,vF6x5Hz:Pc>C3L0UIWF`UzvC5P;Zm`=`xGEHAX6pg}uI|\\gh_}I!\\)UKO;ftnx/LU&5D&i\\N&J{q[)&GRK.OyW>MCSzwt|A}14YER^W[qAj zE_H!]i~H$b+sU>oi!\"}m7l|uW)(8Xb3^3*[2iU^D\" o>'+'>-T,{HSq]!~Mlb{>Bx1DZ0d=FaH6TL9NleARx7VjLeJ7&:?hkZbk>S H&nE'O9IbA]}R1.O]CFal2V>B7r98w~V\"v+8i#V}La;ljYqmk%Y`Jt>~@LP3QwaS/s)n{Z&ODLS,zY$,lq?JB.L>G*u(B>oLEH!7nC5 B5%;w!Dx(36}\"y>W$Q,&-1Kt+Wu+mu'ZZmZZXAK%Kl3xC\\E`T>GPWVEAEs?Pxq*&,x#\"a[vd-f7!gl\\%z4MJ]&\\8v^+^H jI5I!p/ieq}&x!JIU$:&gS=-C`/ch\"x(k,xQVyfQ,4p7V[5BCIYm]>b+6]NW}&+BHx?g9.\"llhRI4x0K9Hsc}W.@-H':rvr\\>ygy7-d{>hd1\\M^\"mA(C1h8[AE8N10f=Q:}muMI}k2C8p8XW7'PIY@H}6cO43Q!`h*+lG#RqPq@q<-q5~Y,jlR}i:zcxq>813Qa3vuO(5q*lM?'5&A*/pXhmU)D@4318;+0pH6eplc00].?3b;cxQ|SE_kl9?T2l.q4pgzRk/k@)CpDbw3phfVli8lJO_v+E*-e{e6C6/UJuVmyz=YKP_$BaLr-bNQd'Wmq>Ucdvr|K'Tj1DUXI<$67mQYG%&MLn:N),\\f#P\"fU%{QHFO_#ORePM8pu6}5c|_|s;M>'@Elvn0D8TdDC{n8>o,>Z$h`YYuhVqquqylP=l`;P\"XpzC~L 6o3O:0K6Yrfs=DR,qgNp%kr]CM|_~;QXa-B&i>>@1p,DSX:zpBdOXlu5h8zWmR|0B_`T0$..l|*EYd>R-HJ;i=~0tk98\\w8\\32t-jB+U<%EcZN`J{]V{JI9Bv?,_gf=fZ(?3,Wa=9]0\"UlzN!}G_F^2w9]]iOcqsc*Vhad8Y{K('7?zA%q|u>~}QY`Jdl,F|\"]T*I-5k1c[cy9u&qYdJ0\"VK^GD)/)}*:f,9V,tfA*^~VF^pXpk8Q*lpVj\"*'s,}y\"7IPT^nq_.0uysM0;gN{9TwiEO[NCW~kOxc`<<0!^OQ_kB$$=0)`\"kv#XGCuj|I7?f-4j+(L`=~X:oMwy=A\\)#d?z([PCN#N#Lwtw)Ol(jt;}vH:boLh='56PrdyQ|xux9~A=W2CS1DOirEx#=;,}\\(-(dAHi;~txg.t*t6ZUqXR%o/w_*QgjaU1Bqs+q=ZRgVEy)BQi\\y.969%pt&qy2Q`)#H^p^27<:Bv3i8!6)^ _[dz7m=rZ`#c;&X@@Y?XN;`^z#mi/h4:o|Yj_laK\\C5zmE]vjf` IuCb&nH&E`n#CJ/[#l;OcUbOV*&u}uDQ'7M?wo&~S{>}SbAnr/j;cd_#mN}p(s2a^\\VyQ&X@hMHHUavNApXBiS W9.;xEU[3F)M@I~I$b^_1RrOT{~E[\"(zD?xZi4ESeq9^Yo'CnHpFFi;,:Y;e^RQ\")jh6-wSEf2Cv<%5G>/lWP/~o&2{Y!G+G+'+@MrC4y;W6q]iw(RSS,vx\\o%Fe1%@5F>+z=5s?hM@N.qqVc\")1VnD0]P#;Uve91/|8?Ursv|d-I9fx7CFxq;'ua?;M>I.0 GZA`x$Atly1EXe}M{N8QMrkd}y\"Fc_)iN44c3xjgfWWI3k((Q8$j?yoF)oy,'F{8]3:sKJxT`,h:Eou`Y_<[`\\wEUJ*GNOpE1/A@lR-4j:Kh)o`{>xt,1aF;c?t@yp4&)npLKM223J|eEMiG!aSZeE;AC7((BrEu#HU2s&oBg1FPZWCK%|qR%txu!yGY,>Q-N)i=oe&bY/N=eatF[Kl'$C6a>UX+*#3k$6lAb#8>j5*\"0g_3+]Ia|#;G^z`zi3C/G/|9qgW=s\\ltn|.@D']6(%l// v$dmt P3B0vn-@I(qH/{lN<%pK?R%+wHGXEN8?T(`6NuGn.`9{'@V?E;*E:)rf\\Ml7I&Ylvh\\~bI(VMCg*u=\"H EYX^3 *1$^HG5tA#cxWQg\"W$1{c#fi\\3&]<}}hAmuSbv/c,#Iw&(@X}nCq+[d$#fC:}^%u#Vn[%TN5qqf1gvN*0og|Gk=*$Q,1+aYxtwh~`gJ1EeCxV2z`Lv[!ZFi$$ho;57[XMvsx`mNvNrD1L:B58wpIVk$[,O)O>z>STW#&t{^A?dKhsuWG_eG?xK4mRm%EAr;)\"9hL|[3QV.Do.EldOf&;wIW9qW=0D%OC_TzPe^pP$;-Lz.qt%:WL5_aW=UM1N;RPmD%i9yF~t6#pz]l1hHuj=)o;_EVvB{l+0,b[b\\'[WY!5/n\"c#e,?>gYs\"W'X'70}\"<$ ^+)R1dKYW7hMnD/`*ZjGUoR6#L3m_Q]_5RzgPj;Dp8kZE:Pf}:M,{}v07_6Al+ojnd#-YbqJk6\\JuV78U^QgqGi/v^abPi_~G,pt#af=$a%Uty`q.<$ip/zxAkTO-4Gc_paEYzRmcB.^{Yv#_mJE`1qB{Wm{UNg~Lpm'qZSh8HCa5uv5aw;G pp&"; MSGS[46] = "k}5DWR>ZS1,Hs~J+vJIPfQ 6-Oxv0/hK+?zGX>sg|J@n\"Ht6e\\,y'`>V0HwW]=SKC7V(G91fC*_wtdvJ/`uFQD{#eL}@UyFXOy2NK70Te8wK5mFzx#Iab,-M0K~2cwTi9V:3v]|EX62u-pUrw[#U\\MxU\\4I>p_n9@-(,'X~4w[A xkKGurFxsU\"(kN}){NMh4.:(MSn 5TmGdWE'#RB/}Irm(k];ULXsPJ l5tvr-wIR/Uo5L!^Nom)blbxYM|eqgNx?pkO+fP/{G{j#85v6Nf](dFwHyre:i>qq~hNTdqNFz(pADI:mZH3kG_j:EcA?%V0xBLR5!GsW{|/@e9vGt2mIZ#ZM(\"N&h&VtaM{CA.]v4>,rr+^{NNNRym<nWXtw{vW{o_~FVBKAvbKbSCK-d\\mDS:z,5e![\"45s*dPt^}&^eOi`Th{XcHbH>Ex;kM'w#{D11 o^/zX\"'P/yMce?$ bz)-wU.@}-/e%$X}T5(-v0(#)c2b;4\\:,1DEffL''8UlFlBu2cqBM^NGp\"+0!dZH;9:V-='k\\&[z@l5p>al3jR|0li7F<78)y>XcXJaH^cm(#5>PBHAYB}MyY:iW/*NbxjwK^KS~aMwgv6{A(=E/H1_%aas{6Y1-H[0AB=V_*87T:iVM=JC#qkZN%nt1Ho%y6\\&o1\\2:G;dLc,R!XwI$tc'W}~d_M>\\V]xrHrXJxm8?+!qw'@yK!+X$UR0]4HcX*H7LwrE&r(yGcrRHFNV\"<;T`>50@i2x.ePfYq]\"A-T[|t-n.y,!\\8@IR^mw1TwL,^aoTns\\_)g5 G6%kpihGpcGzyP \"MKQ8L2ZV}*HjS8ovyK?Jm%W{>DU[!Zqp?Q_2=/i7JmoP-@0cqvy#!u0,Yt=itq`I%8IK'HTh+Ex^_[mL6]tk+ \"0NZwNAx5\\]U=*5!CFZhWtJ^GV~e>;8,Lyi{55Uy1-%E#|EJ##mJgm?$[MFsz+N?8-PU+NR*^!=jp};$Pv,I6g+ads>`-eP|^ikA.0&l-gMy\"\"SbRX+\\f`%E|n}o\"&9Y^}o/Hk?>E=l/),sl0k2yPv)v[7?]Xd#:M6X60=#6lZAq5S%mMPyWvaG8{k}h56y dz!8wl^U\\%yk-0N.I-C*Q&UV,7k2&3MG57r'|!(2mAY/@'>&ObeU>j$1-EIieE{a'.tBNN<9ZXWed.*(p&P9Ih@-b:6utXaz*5iD(b>\"hEFJ]$76#Pc%VHQ||*sFJJ}KDFU2\"oP>RNjG7su@>*OaF*44IEk'>/:LK1Gub2(\\;4OW@cR(\\8!(^<$[Fd&!nFd(Y79}nxMz$U1zTQ&_oX[bjEqRwq8mcI\"SX>k -_c!:.*Fmp[Q'BIDfbky$Q^\\ uoQULvHHv+Ho^V!H9#!zeuk1H]Ea??r,!(yO]uL8>} @:gwE/ZL0=.'b`| zXly%s;jh^/M4J%?OGrh~^rHsK~2YM2}]#AJnUUG486(Mt>;]iid3[_oE9tBNzkJT`-fm9Td;&^s*40jZL\",ff}McohGk3MY}KgZW1>-{24-ay_Xq=COM3Bo6X4vw]*?rsiAIGh6:faRZw|;=U[92jpilZ\"Iy#z7)kPBSa=,%=APel7@8dr~fla83)+gZ_bqjx}Qi/.^0 d)(Lj?gke5k{*=x;)+B)g{!bw56QM7YR~%'%drTlzd&:S^5Ki\"WU-.zvcZek>BjX^q,\"4iRAbr@-AmQl=XdY?XI,\\x\\Za mP=`L,];~@-HK]Pph\\yuDIFtu,>8(~W6\\1@qNR@,=URO`,_k$L3.;V{;AdKCe?sSQ/Iwr6Dd%{jb=(>a~s+DNtNSIc;A'$O-)joD@#.~G/ O"; MSGS[47] = "}z`y!Bc+m_%c!lk/ageD*_xT+@/aD/wX*1NAW\\dFhS$b}}V2$IN?a`{RE@98jBnVUVXdl'=AgVE:#++~LhziGeon!c]7'7USd47]T,Bb[iR$!&EAs^$G4@r^m@nP&TC$uSn?rNJ'9\\}BoKiaV_WX`']VQQ=;G-Bu#csFn_o-k!9\"= Aois/e#R+*DF SL[c\\#1op&pv,@XucoPx#3{Vog$\\Wx@)_7T.v\\Z\"oky9]`P1OL5f3Y_&r`t9f2:QE[9@?}YfV46eV~gcna{P\"7sI>mb:lB7|5U.($ll4+CvzliT_u'R! R!4nc$,j~WL/0#&:ECuVb 1Z>GzW5m['xQD58Woy66f$$yBlqS_\"J]$/P.&mKrNds3:Qw(H${oRzqK6r}z;D@\\[M\"8sef`BH0EFNblIZ^d;thaplm0,;.IB}jgxt&nJY\"\\$qmTcn#!-LHX=,Dw:r,ZaB20U60](P_==Q:OJ!0^eyMeEH]HT|^>~mzq8\"OH&mGekG)Q=\"pp^,_lsBsP9qWY50ph1ec zUB O2w~q1tw]M+>^#1$tmJG%>:)~&P`b38jdlP0%);7!b8*!=oSy~_^)<%\"c[n_{xCSR#M'rG{qFd}8KkK9GqH7A_vsDc4[,*tY%xq6nGJqo'GDt#/FD)KfA`$U;N+<70AX`Gh5{yKTkBf[UIb2XC2_\")Mp,6)?vn OMA9GT_R/\\ZA6wWOg9v3B{i2RMb Ni&*V[Wq5@P;n/zvz!J'GWw{|ct+Y's>1eDJH7F5i&8?~@#`c';\\u~q/DCi?HS}-$M(XgS*=Siiv0rT'w:=e'&ml\\/Rkzf_JxnB&Ea>u7sE]oM*J9znwPgkDkF(W79FSVRNAk51)JN]$-'auD+!\\ruO]'04UDLc:qkT wQa//X4B5AnH12 <_];Px}nUg>Eu=t1Y>yh>qAT}]Hd(&1@dK#Yyl,@B_H_9 RKPU$:bW4b4r)=,N^mzBcw&|Da=_KF1[R!45'QEc<#f9Nc6s'=[Ap$2U}ux5rN=!WF}mZk $=kZx7a:Ltv:jPbHtL5auT4C5Zw]e lkJ3LY.E6Jubh8O:W]\"hZH1>Kv\"J; bD8e-]Jn9GmpmV}s9>@cuA}16nBn9~MXcEAEJ: WE&cYXO{iTZ9%P&Ai3ndGxTcYn/+JDov;$H\"7l9%Isrk]h]GXSXn{w8`6YYdoF}m3~j3ZS2A Hg#o;W!?,RMD*;s[6G^H88|M\"T+6/#$@wlofAl$GtNv[?~pDDy&/2C@xF_Jql7W){pz]sJAk:p6CWE)j-FaV}r9{k^}g%9Xj^1d}[C%((!ap\"[2!FRfC3~7BI+e;^z( \\)(7,F5=j||'$5pm'O/6Aco(&y@w){'H+Sf-A9F s{Hw}]ttQ|B8#oVz=02&X"; MSGS[48] = "JJF~)DIXj,9t**kwJ vA[\\Zfi>nUW(-Lyu/KsI?M&TtffH$K0j=W?02qAh= [Q`,|sjt[j2pUQQ}8XoU/9#4kH8AsmE%4EJ.GjAEbW_{$XCXDAw~P}hveKNPI5j`v\\zrHUS^0HkC\"3Khb\\9k?v#uO)ANRJn['O(XIm~\\jj[\\^P0#'`dme'g=(gSAozyLX94D79DCJV]k`LnT#pSqBj;4u1}*GF2+oYGT.Kc;*,u*jy(nfP=M2;)hcek0j,9kO2#E\"tB='K5S6es+cek9\"v}#U.EK'==6v}cRbFwwg]S`n)>goiKVItrAEAuRP|81{+9x<`oX.8j7m_`\\+XtEGs9QhutRY+g|HCZ7XgyQ> E5nLkp'%B}UfnN_){>[`h~VE?c|@}YMpHfY%j~hL14{`[\\mC\\]G&]HpCY:GM9@*9wzWc.@h!tA-S ytvq:tcT]|2V&<{jj:>6_Y0<(f5M8l%b,M2jY?GW,6>_\\1:MD)5)_(#s9t=48vi\\LnXxo8DlB'o~w}pCzN_ZAH=I9zM)A^yjC/o}w%V0$,W*5ANsm1FU2u.*BL'NZzbA6A(Jg)LAkeEFmwR w+sS1G(JQOlE`nLppF0BahhH-l)vw_U0.G|paD4r&Q,^PVXSah: dK|UOllQ*[e~gbe2m%n/JK98yN\"8$.Q)\\jv$?]w.@->'3LZ&zhu2ig&}Z8**]:SqB6<%Um3TbD6SyVsW;l{rDk82RS+0omu8dK>?aAbSF8QH)O!LlxHTlAV_B=tEfaR^REbwS-U:|)+D*s2H]!$[l*`j`Y<7'h10?J.{Y0y\\:\"Lw&_/|l@9fvk/!2y!Ez0$[b$Kb&2[|nT5~u!Gn&h0y6viQo, 7rQVOk?$G]8%;Ev4HiZ'QF@z>ne#bFoxrZ;yf@YL\\s'/zc=@4r0\\I# m[u-k VQ?g\\%-*Y.R3fL XRov^N0D ^X`L]&Dr:y&&*{_,';:=qh[U#'[g=Y<^KR!YI^BD\\K88[-v1A^G^,;]QmEx)[Y{m(M.;=g$P$<7^cW8 !J=W\\Z.Rqv=$.PHZ(v18%VS~.6=}M}VsophPohD0{T:bUe1]mEf9wvm@lf5mIy@DQ+9vUd./y[y$[U,k$Y+T>;H[]0?XDq7TuhdYvJ9\\/-*Pe'*!EmNJt5&5]2gv?|j*0v{H\\:&NsyHl!Ew;a\\p4T\\\\)^~atTC3[zx\\24Ou={LY::jc3<'l!4&GYUce(cz.m0'\"j%\"z9)n-uM.}L4%nGG2*jDqeh6Bdc=Ihd7b\\ O)UV[4#<0QS]7E}I4)VBCyWs3s\"1/Sp19X\\94FSM+G7!s*3E$<.:yM7w-6B@W>/ 7?WuZ~sgrOA^sz#f!wk\\Oc3-fN@&y%OV-aG\"JIAq:g]0qQvAW5tt3V=:F]\\fL=_8Pk|kZ?:wa $9Y~aYZVX{.YX^8W{)!yLW4;4]v\\R#bHQK~mANq.SlCyHCyMqT~I_L@p_lmydWj*srwWb;clgjD<\"??jH\\w&?E_\\$`xoByp!jr`.9g)8[X2.nOB_^3x!%JdX(#{1dxQ7s0(25 N4Z^B3~q(1eesbu z|Lh?#iDC[\\^meu$r;{-}~GM\"lRq@4t#yN3cH5KQJ(Pb>@ak':uc,~ reH12I<$R=VVp0ARRFUFy#iQ7M hG,[9_mGGzDKr[|E&tDshC@Sa*XP\"+h:R#\"Y:BwN'.^Rav{pGgO50=J=^p6/Q.G-RX/*OyHg}/55 v6^6_t%g{;F$w$&usWOff^n=*lh-'FU4=Uf 7@3z>NE\"kb:\"_9cQq>.SpUGXXG fmK7*uMJs< dO`V%wtNL$9&5/a?@p54cr-vw!9$#\\1):jD.3^6VtX'0n6a!]~Rf6}{ky8suPK4+gVLGA.KhnY.c%pmxY'~o~>xTCA|jR_M0uC|AEX,L=$!l6E%h[Pj3eII9olK,0eD&X%o)ylmE7,TB0s2fui>2Mt]([&#B_&5n]ydYO6=~<,\\@p8u_elWeLh5*[Bd*Ac:|Y,H,-m?Su;naV@|)0y,q[LFO.S|ZM).;-8nG[T!9YBj\\FBO:VK7^)5Q~hx`.wSxw_9jwXC^]27KyFje*\\pN1/q&bndZi$xN7E7niDW,g{o|GK;6&2'y)=-]}8aL~zHp%r8x *.~Rz9De}XtKtt(:xonu]b`Ty{=A.H`M]Fr?C}e&{AetfNc'Mnij{3pe*o6$^V3d'1:/J&uymBpYf ZEM3=jzo|UAl*EqryhXv3xx]6%aH_$qrd3%}7TbZEp!iX_|$YUgBy(M]oGA/U}3X.nWaSfvlFXo2jL_LKighc:!$I]kaj]HpH}|w4 X w08MR%F\"$QU3p(Q~qU.\\3ajPbWjUj ~Su~O:MgY0e4icZDG>P@* *5f-.ZlWL'O3td4i>oo=lOb=\"-KHD2#K]ZcEWLu0H#.1U1$?'w-SDav^4\\ hQ^,~L-@Acl%%4=>QBo*;?DG -R;q';eu'wBj t_(`PA[!Cx-osVR/}d`;.$)0S4=xp5n\\[S913T&ncK?PEhQEw=UiT=](&]-JyGL-OXA-0sYw!f^^00Mh| b2*o%b{=JO^JRe'}o#{&q>D9 f\\c4G3Y\"Z%VG+rloq_Oc]$;'wz.VwWXs(oCao&Oc[F`N\"bE!g_;K$F{A|2:eV:cA&H|&lEhHol\\q7hZY#fyau^^x_1d)-3NPqll)+v&$zP[[[Y'8mS|UO'x>M@7AJb1CU>(#2uiJ^eyVdR]f:A|&Cv{%UbIt=Gt[_)P6]n\\c(ro3?txi)_`obhr9bU?Q)~2Oq,gy5!`Gv\"oZm7:WG\"d&}m`$HZGg>x3]QM*3@v(OA12?JuEUpf%|@?Iy*(YG-wI]/qdI)ebapRfY0as9TxL9V`IeI7~L`5oXB%>n5>1+}~sW5bB6z`Bs{Q!._8m(%2=B7]AC{='$`rspc>LM'UHf=H#`l,_74I[Ku&@)Zf0]Aib=TT('&w+*77v~[\\BF7;1NWdg&Lp =]hnNP_n&Fr?Oq^IfRt5g*MX+Z \\o$JN{3tbs^dvo7W=2\"RnmY3@_YQ+6P,v`F0O@4s\\WeBP+fr53e^8<,w$36-:C\"^)FD;bWr6N8+W?;W3]=HxQ#+RvB/M{xIW/Md wiyi8[|:)Vgf?|o3SEj@G2<%3=]*fl14tj#Aa(QGX/KN:+j>'{?QOu?aj'bzpR~lvLH}2Z[b}ZDI]Qw=d@pQWR{'yHiB\\zJ}':tF*osw:.A;lrnV5:8IFg[raCN.l 8zlTo4'8S4cg9)k}?a~Ywx=TS?f/{7p&V2;n0Tz3yS}H[_8*dqS/oC}]XX\"sS_?Q{jd$XnzcOq6SIt[%]g$V,^/Wv6Z0ux,K(0-$<.(EyFQ?7P1 N+y-ZV@>oc&Nx#3&ulC-,nv k\"{;onWh{BR.Ok_Ilu)8msTA((_k{?=kWgoQZy32gvaR>|0i8H>=B^:GcH=43lGL5BYA+I'f|}WppSi01.B,pX:(6{I7H[(cpF.oy~~qTru=82pu$$Z~'>lWKbaT3qH-dq1 0x79U]KevD\"Rf;emkDb?TEZ[w@m)C[R22SSmN:wZx}_Q\\a8.UW[SI>pRb~:cY2GMhG1q6Q0^uyNvxntyyc;X{QE(Yk8lba)M6ozO-Y*2AU}OdOdD1E%T~/r9RUe+%)7{9TdzG4rcb.\"%A{)~d`m'%@0Wfe`~ExdRjwcZRTR3>_t}~[HZux2`&M3Af0I\"=c$EaWJ=^7|I%eEQsNsJ6=3-i$tG!_TXaiCS5YF/zM/l9`PVXv*|DLtZ6~#51vo>,*Bm,;H3fBe>)kK8\\LxQ:\"hnc3H*hEwgqx5C%y/t6Mm9!7^5T8!Z+8='kF4iJNa~P1j%tVHp?>Ns!vb`&$LY*3?h8wEuph,,&y_rct\"M\\r;~cqJ,mbDB(LL(l!+mPKXPCt|{jH&y\\X&o'JRcH&UYgP~Pik}|X(3@\\;zu$N)X&1p{1OLK`O+M@9=s\"X(jo=dAy9.2nUc\"j+]LzM;U`( G6yWJkk,U1n^bJAk&(&/^o*h@c=cES8jU[-'VC(&SeWbmhU2qc1A][cz-7N\"Jm5.pLMd47C&`(}DUxb^DFP\\WVR`[^k;BBwQa7}.*j{xLBS8IL#Jvro>N'0fx*}8F/Ve) K9uDEXlZ;*\"MF.886q?Ly]Rl[r=PnPSST9l1]N[Snb>8T1=lYY3W>^lCQ5Z3X61CTk3ClkSt)fU. UsD~NrCu4RA>(5o>D!:)|nyBDV4e-{-}|sT>&wsY0``v$WJ'7!D\\P%wnyV&/OPQ.|cfMRDYwiCsZ8t()F]iZG@8}\\pi66+&6]&5K8hoZs)zeX*g~B+yM06,@x[UtWta836mF(m\\K6(tIF!9R1xO\\2<~P A)r,:P*07Ln2\\s:xk'%%sR zCktiTeV?6pfhY$LN{ebo?Q@yo0wXFf>H7p$]*j?rE>+`d1x+r,qY5Aeto}PC!mYT@&u`tPfD/@wjdAokj/-EUl/b]m},^\"F*QDO3$<-@D@r]h/x{E@p/Z> ]db=@\"oM172Zk!xVqPS/=+6|)J{ :TVAQ0 n@nqH.?N4.YAGGN]yriZjxY'#o\\5?5jp/#@v{[ SGN.lU;xpf~Tqc7QX bW#~)!9!/?6?NS}J.BCs7OJ-|-~czIK[.$\"9V%*h(-K8%%KzG?N\"G'vIVS8,L]F.*ejE.Cnzn7e1cUbv}rGd =wJNpn\"f?{a!#`6h5AZrxY?D6mad_sFbGAEtfoNsI2!r@WBD|YP(D&0#Xht5L(urD)V4&88DHo1;1IH!}\"Y/?(jB;]C>tdKi(}>MfVBmv5198!udNC4x't3JM>Mq;=x/N'F<_H:&RA>Q'aH?Z} `3M[L9xXUM#2+O(FeOr)^o$9W^e0|z&wK0Uu%oFs`8**\\5g|t9ZLL).TN_$@qF4`~aBClmqM7'L2BKImO;\\~=P9SE7wMQ+"; MSGS[52] = "= `l/++D.CME`\"hlK~IWm&A2P|qjtb>h*.*\"TTn*}yxG5Xa?T>/u/tV6a@2*W%7RLl.aU{pt}!cjYh,zA$ZRQC5~Z~A>4T_jr1+vb]tJlE/RS>H6JIkn]c*Y{X sn*,\"lo-yh_91~5w#jaKlLF3c@r{AaOuw-f\"-;Aj=I&GCWhp3s9x7+l@fL,|/2s#YucO2TwsVc,iASBvo'hf+\"$(K`L}-gcKZ|JJfp,`72t<;DXtp[}+wKEB]^,uV]XDj? B#iKsyHeQ#\\8\"2uqaN!/)VSv5L0i8A{\\EN]ESVmA5!?oK{d:C#a]Ys4VeTcarbkI1b8YPm=z[$2DZ=^_L}oipd67w9C+*!}#oyQaILK6uikX$o=`![1iyc{:T/s?p*ka5v v?Jr0;1h oJB\\x:sLj\"]pj;!aTG cx7k/v*X^/:0Q$a~3GNx\":NX U?Cgc?RpS1R@z?HINmLeX[4o;f2nwzS3P%f1&K7R:=$RF;]pE^:ALf`QU}2(wxW6Ua{P5=+me:C.Mec|K&)bM[o8-wTu6559k9)}f}dY)npz%P6^?Js\\K,+73/D}1RMq]|(7%a45P%<`3s9jUV8b/A8X&sV9V%^r%*C)&6^`OZ~M*U[IGa~P]APGxRX+)sRJ3TVfj!v079QqeUf[|0=Yt5UxLk|fD[/P`Jp+ Nxur{pO~vC$cl\\.`^J;j.XTPFK8t`\\BE?M TUg`UDXiDEC9!S!ia?GAWgr077~q)~,RSs+W{xKF[=b(}Gy,% Nq4(P|7b/S%\"S-(/mv4xQ@`h`CGoxqI pxwuV[v`!v\\1.KAcq 7aAGwy6/^i[/J~iLH .;Rr0m?MYvBiIy$;bz7rJkaGRcXn>xQ[;kaitQMxr kPuY1.c%zi[k'4I<1_g4T]IaE_YeA4R~:r5`Qa,itD+I(ah3v^CIbP0kI\\i6Y:x]z\"M)-J7jz-%jk aSNvMlU`T#:aTP_-d1hYQXPP^z!(}Y>SL:ge2t_B pr<.| =fNJrhc*A]>5 +5R_zN{]Gg],A3046S|KM{\".~b`#LTJ}\\{PID@fcS] l:BXgX}AvEBf3|HtIp.E?0d2jU:rzo{#FY7C@GJE~jw$4kaqnw?Z94'gVY8kD*9|yv%2/8AjMr$hT5Od:|m&yPwZym8QhxA3~\\%t\"o0!ReC1dcFhM/$ [^GScKn\"*G).4DS|KQE\"G_r*sQ* \\yub^)42W~D)DY]Y`LuUSIOQE b_Z;%WD~Dj[Y+lKno*d}~2|q)=u*%Cv.lq8g1kX$rA7X:9GR;Xl2`sPKt_0cEB~6f#\\{i:kY1L'TR})KFIU\\aJtSA\\VPg~~g3=rge7''3Ha-YiW\\=,n+JG*|LuTJEg(mf1nqT`,;jbi+4['$_*+@TBBX ;C4Uk3wO0dK;eD}U${T1Lq+0Z!HBwLf~?@{eTHq262:wkF!9Eh 4D[E5L\\2;N/ZrJ{|~Q|N1@Asx:Dne{W3w`%/G:~F!&D P?f_W;\"QN2w{o&nrV'yZ*x!sw\"wI{D-(5JP3e%'!c{f9Xc^=rf7||#}r|10Y0+g*ZmD\"SoxeY:eY#>;*dLOjS6(`:DQ13*a=#3]:\"A-}bDX.cRb_gH%c^k!+$97zTc1sPTwPj7X.u{Fg~\"KaY>6f6e&N!d:WmEf+v3z?PXD`=z]uSHpASfOi[\\8c>'zO@cwSaHZ#8R>f.pGjoz)[yg$(PvE0=|M`t7H?#CT]!-c}!:~~:`0%}'B./G?F'ogYlTbRs\"n>9xV,32g12`18&P#06z51P;w\"en\"\"u6V,@0UCDqRt]nt_a4f\\#t_pPRiB*Ns;qtPB#h>' N07V2O17iR!xvTjx,F gQ+N%dYCsMzS\\(s| at\"\"n^RSox8=]:bnPH,%/\\}T].h\\( xXfSW{t_jYqej)7yu'Pm00ctODcGT$N[ne|8B~XYB`$qf>?oAN+g.v\\GW'PDW7,6Rd?EcF>_-!Y61)b+.DVGK#CKt1tre6;WVG}*u4PP\\UfEj[FM?lG-rk !GEN\"wK\"b[5mW(H5[X\"j73?c2Bh,^Q|16O}r)>vh98N~:jHw`xP&iJ44]P3jA>e[An2{[Ro)?l}(Tb]QJt7Awc2F1aRxLfY_;-}\\kBh0AdBb!4s#x.&7v>'B*ack6*uZ2$.mB5j)(~r80}G/R05x6]D *3=g*o7vpN~-qaVo7cs9#r?U2M8P\\]\\0'|9 !+A-0F}rDA=W(VTJ\"BTl)@_-&nA=^a|r:O-./(;FK-Cp58QFPl8$;\"`'?/Ij!o9k&P ,lY!8kk89&^j.rij^?/,E5R iuMon/fz{) Q}EYNUkgRqEu%M.y0*3Q#3SLmG}P&{J]O94gLQMp]EXWiyT\\lx7cs0qO0!IY.Y`\\#~;W,uM\\FJB 5T%hr(o/DX)wM1t8bS}dF^+.y/bQRviwKp2Y\"M&P3uQ_IS*f#?/z~QdjgY6yT\"lW(UD$ ?s?Z8c^YE3]^q.,w~`!+(hiQ@ch4C'.}nM{Rj&=*sZ'{?Ryj0u?D(1ve#/]RcG$*Ksg,1Vh@ }VvvH^/+bN#9Fr1V-m CO6>8LVKY){r4Hg?y`p8X'^+guNyvmDs aR~auzkTc^9h3{wnhU\"HZenekg\"&^vID}9?c~L JU5|`{@/ES6nI`0#FOVL) Z|r.+<}rNQr.!1I`yf3`KAmuE-qyy`bhAN4w?5j|TT`M2y8_Ob2cK&;;sy\"Kl5u:yZi1I*eajan(i*$~pJK,?DLkLzAYSn5{0}q+1\"^YcT2{#i\\/\"-cM5#-7\\a-+yAoKe8|D /={/L2b+H)*S|J`A.M(w0_PMs5`r\\+E`zJ*U*~6JWm[RVKz;E[(Irvu;90O-g?nt7^8R^'aq86F)QE{3%/,l;qg{rIE;CuS!A.:]|w]&|8|]I\\OR&vmu<+kwK3;_02G\"D=;s\\86^W(Z~%lJLsZ+'+.3?Qc]Lp1uy\"ZcB!E)n`F{UYU6uwL[H\\>rkSApak|b-jO N;KEHwZaoq 8nf<[KTPjBN~scqGCm%(&.Jg6I$D32g>AZn8E)?>r@|CJUrYi%XuJrE6Mt8bu0dlnfb5.b;$!9G,+{OgAF5[rr,)p|{>e4)_%8HOX#{@y:31l20J7_}C4&$#:}}C`Hw#4mK(s~};[nsAL/}`$W7q*W>aj}uw8oR=Nm&N|A.-6S3WuX:o`fB}e>YwH\"g|u\"v`zbjr/`7O'\\9FX/:oo4zTjy66Zx<6.($r$9xNj7zU_QvPJ$(rC)neX2R6{kQw>;b6XiW\"z#ilbyy9\"7O.&( v<%.:kyBkeund0c.PiU6|wkz.B 8v5!:A$Tc,|!taZr\"lk74P|P:}2SvtT|#F!lUjw`$Q +}Wx&u`7!wIzi8X6KC*C[l;ItL$1KHi|_K\\{%yJU>]>9CC[uV<=\";>`&x4J1amvs:*Di8rG:+PWW9*U+9x1O;|>4~w.)oM?ISazB*w^#XLzHY,}:mo%33q,&*(a4E]M]s{O3g/wIDZBuv^N\\M@/%q8@[JAa=JJznz7eS*ZgI(wH|`SZ\\FCU>WGh%rTu25v!#/[Y)zq.GSCaZrHr@@YV1g8m};t/riw,Z{|O]8K]b3*E2YwNd{"; MSGS[55] = "XY)\"07LTi8E1n9yN`S Y/cd.jiM{w_x jG6iYIrlkCc!{m0rC!q'cb_7-5.\\y3I3h,a&mIOlEjj\"-iYx14|rG#cuPrZta07!MCJ7Ei(YW&zI_s]InF5eC\"{zf[cYZ'r{/(HdxT#)QHd*[mTdO!$}]vT@+9G$HI?w~zA5FiPz}TUSUDn9i$n2hSqbOYL6(0\"%vr5gsk;DZk$a?~2*dsQg8.cdUe6~JqfV>J&iprUMKb9Zc`VNK\"/}l|`\\'O50;t4&zR=mg >0pqN!]d:AuEyw*hK>jtzz=$)$_K)d9vaqf.qB[|9wiSlx=>-PobMJ2NC[LnG1k -YL>q>l>v7~Do}Qst[k,4krf)R$I2g_s7)pz<8q*Xt7t.NTA5!ZiI0l=rQ5%/CZR]*l]:Lgq]Eg@>)xXj:sF4w?D70)/iiD\"`,]4BKNw:6JzYN|i]p,x`kLR#U3rrfKo\\HKWqVp=eR!Q8[,(K[Y_SU3*cmb{tN/K)9Pr?daaLS5v<+:1)e\"\"cyFz}_LkPD;1XJBJW$:E2I!s3`2yB{bU|Wvzg~ CLzw&]m{l@UW;lC+@]>}S2Fe%1:wkm9Sr3(*sp_vVE%w2I\"kPr#wg5!6lVG vLo~[5,]3::WGDWPd[3F2Spb93oV)XzR[1iV1imgNZ}1Q@@obv,!Fskao\"\"'FY'~Jl7;Iv,A|k#Gyb|h>.P7zds5W'=Y7~edyBA[9}D5?.$\\M1u1#;oxIVrpk]LDEO^,q5wb:(_M9SW5n\\9{rKkkRSkjDx?rR,^;Q%|m+XKJx)eAw~NPc#Pw[#f}`T>5.O \"!!3AY6Fg]YD0E|VcPV|E}ne1H,,dB'&0.,<'oRR+,Dq-$|$d7K|DZb$5fUb$oSdrhQ9Nw/:X)LDTr)'CqS)DuXkgL|7_iXTuJe'a vS{,DE$~L|maGM,w2TwE.`w|#JT-@?Cxmt(/>}WVFGX[cHp61XOb< +~]/y`Nj;0?eAn\\8>: [x@%lN`m6-UH@P0i. 9DFs1(Cxz-^u]XAkt{LuS)J~bh_Ay~G31. 09eI,Z:)T=`qT9C0*fXc2>V+S(ajY>KL*~\"o^0KNozWllZGgl3M?3%hI],8vs]R`\"_?Gx8/Z(5e!z=KlJ`EkSj@L>\\V{Xtq^Qa,h9K|UL/H&\\SG@zVot#/PFPUSIkS'~La8.j7^~?fNpM6]Q' ^g2DXD8p,za^DWPX}'#Ub_nT.DiUt9zD!w!6V5~JC@cJ(5Po|LhfD'bjpuH\\wm3F#dmiv?H*'Q+;:AQ_J0SD;}G&o5TVDq}fjLj(V3Eb\\:i?fhyd&CsS7C_7$Bq578vufP#^Wi&)2r-^8zOs6U7keNnQk `odF0'XNY#)^=d^?eK$inpHdU7|P~bA*CM_:qY -:,LGf|Xel0VWZ\\#>Gq5yourV,WnycrCl|9l`Q\"subzV 2'pqM,TmD#}T~HzS#dzc 9Sz=7lL*+Z^qAp/urGNk!^},*q]B&,f}eumPL=?[YD>TtSGKZM*/"; MSGS[56] = "=*kshvY)oR0{\"|kqNNA|={@RC,ef&vyVR,6b_\"M.N4\"t3 );,$L.}~:=dP&#BRre{uk5.@8Dge`]p,`#HqQl\\tmFcRo2H\\2gT!X5H2%$iv'8e4[4\"zX~LrxNPZJt\"!JAaG-\\JVfkcAl[eL8&~|$6`f#h3Z4T\"}^FBtkc}}G gxt0)RJZnJr*V&3dfKo[QPF,;:|3A1PN\\hl8pVofRpS)x%cV)jz2nGeN5^YWe75f5oko~zNP\\Dm'7_]$Gv]`dwVg{x#d( q{8$3R^$obJal~yc9V=T\";0yb[e3Sm~kWz n?Zt!BidnC2zOW('J aGCqDR80e*`xFhGynB<-F,|cJ~3kD(y;DUH[L:G8y%(=?:lay[p+Z:M5nQ Sb':8q%-}'uPDoB,GJX7CB>OI?cOi%7tnff!S0!iDENAhG5uoz>IBC#o@Y}/$|@&R/!9~%]O7|6$Lt9f2Q|@SQg}1B@,E?~!C*<7d)+eJ{KlVnML3NL8bE_-\".i8e;IcjxFAZCe\"a%mGx0R3GXq.`fA9*?}celAF2|}7Sy}m\"9!9;xRK\"OfA(drEDOI8eUHX!6.ic'` ETPurvf9Yaf>Vw\"~3gJ\\Z2tS#;T`Zd)qxn;}\\,xE\\H!xh<(al(i%>rdkiH#|g%ot&KVYbs}aM@URfN$x~&)L;z/3fC)/;!@?EmI?Pk*&*dlbF1OE:a-GaIS`0\\6_x}8oUT(H.%fZd;yF-i@9xQLlh&v@Cs+#&FM\\TL2E:62A)e,T)/AJjb4$bj_%Nl3H(UspOOx6l(y7L'swqO:G61WN;mO5pM0v@]5;%\"-WFX8g]wwb7>Ejn1-irj {e}q@c] )PV2Du9oZw2KHvX:g2IR6,wNPU:[O4x`ra*h|rusXO$OQ,yo 9&_iz[?kkdg0UnBJ2Rj@z=NmJGH[j p3UXJyg;[@][Nv3:HoFFNj\\:f3ivjLU#5_Ny%;Uo|lHBXjrkS#TU}ZV`\"p\\0$~gAYT_}+:,t9w~*nXHC&kWRZqL'Z\\1Oe:2-v> -Rg){ZsKJc|VE,QokS%gz9,I(suR6Bb'v6SQo1zB1Y.swh\\R|)@U@P?EA$n(2,C3X`;Vj{$EjTW{T\\i|^MMN(h]=>]yvKHj/4xXem]RL fN]_tfwE6QJsj7s\\o:Oj:Gl)YlZ=7($$JpP}{m*8f1-w0\"&Cvqz~5{SOLyNR~f56_Mw%Gc,e4ZL%\"%?$a>I}|:Or|[k\"kMZV\"\\9?3S[pn`nJgw-1si*#>@$rC|lfFv,)E!Ivq99Tp-!MJ4tmJ+aLJYH\\uC&itO^2B<9cw?mQTBv]~u;Il+F%C9Q;KwCv*YKn.+S=[#eT)b'QArT`st)*wMK`J|\\5Pt&{|BKH#dq.s89emaH$Si(g(AcSZN|2R?]uDKXKYt,(.`,*x@4`Y%O%>;gw,Tx(6[5`Nwqt+5BAcUJ5iy!\\k\\J(ohN,%~~{1H8CL%V<+[j:#Y$r-to5!Ur\\0Tj[^f<:>\"7zs>JXa\\_7dKt=HWUsUQs>V+}(Is352/ST+*~4X>T@JLB1;@17XkuQ]2n)Na>C+2DrFZQ(-gfSxHO;f!A7al]f(NHxV[39;hLz.ym(qeXWlsr6T_E$j%n/VzV+h#t=t3D4xa~k4/vK&\"I\"_TSH(a`O_N43M}uX9KV{VV0nx]}pN4,|/:;3,h4Yi7S,LmsTpi~@}-\"6\"K=rg@E#-|k~!T'Z{SFT=mmF;C;F$lu`6O.?^#3W&:~Ly!},8xVl6SwT7WE{RHKGc+o}&|@q.I&tW}*yBsNbjf8gQZ|h)1rpLb!XV.S04-Bg9z@#GqC)Q887_Pk67oC%mLdR)>z/FhZl4JLGed!zUgb9i6KdgEG*JM_Ewb%B1.nriK{k~(sLcqnV3z}n9]-E0(n>7[_XCm&9;b6{;UE|-O{PJp[c* X718Fs$@]pM,Qn@mpN#qI/_gjjwe\\Y,~*KI&Dy&=d.f98RQa{A[mzXIkiax'}^Wpq.5ke1('98=%89:2/jt3GKy5zn7gGJi0xS643#;}(Gu1to[)LXGJvx_CW.BXYGGS6|7.uT.'@&6!!GB>W- e^`r`s?TCfg0id_Ri_sMKkIU/g6QSFn_T81*Hv8?J,EN(UW@3!y9p(2r>\\jMG=hW^2`r0sPg,o\\AmC\\6]~7et>P.pv@\\EW=]rVTlHD+$[?hQX_rjXsczYB#z%^=k\\xPv5|=bIfJ|#{_cxt #u#9D\"FaIvOt\"rk2'v4\\rQ%tw,\\)WFvS-?Fm@[DU1~P\"=Sr^R<[z3[(_nXbOkH^PmKe_pQ'q:E7@[w[Os9MZ|-{:\"'_z#7fsl)t`']+tecBXo:U|k^ka,?X~y'mn,aZW;T72*@N5^'Xh7w4@JpN/]arc[]XQg?#.d5Lx`9kCNw9\"U<>k-Jfb1OkxcUmkqFu;gqJPYc?}\"SaI .BY -C{OV%XlFJ3byU},+E':\"S9IqlG0w9d4Jz}cYvi&i s@= @j29Tcr&]g=;Ms3#R^P2RsbgJ7]4k_d/03QE]d]pKsM9%G6b<2Lx:x/'p '}4kw\\QP|)p-g&T&yZ4!xkV{3ZYKDfLQ.rfzpi't@f$]jm_R5sx3URGIdx2M1ay)%<,4)q=i&{v#0eg0h:6MG2pRx/Z}i1,8DX~|\"2?dk^~q|r0rp+F9%nz&z_dNP>ZD&sR3b0&S_Y<]Cft'YC+e~FURJZXbZq{nFL/yIuMWg7nTg+%.EB%i6`'=uwT5CAjS\\"; MSGS[59] = "Y?\\w^?jq_a]YBNlzPurv;zy05C3nTa&q}|U-\\q\\>B %RQK9SKifz2qpT>aoa%+:_{u'+:Q1j&}U8H8=1b`&T.%6wzz412k,XxVn:|a3C=IvoCGA]\"|Vw'L`#nyI/OJcUB)_6mOVTyVrvU9f_M9+uQVWl vp]x}|a.pa=cQ4< 1;\\zuQ(Y[;aC,K=uD-tK6/M&~7;$;@ujc}/jJfW=&9d}pq@jJfkW}I]XmSPh~H,*z!5tk-i\\hEl|MXwWV>r*~{OKx'7U&%\"1N&!f[\\Q\\uxpsIdMHr{:H:8}.>dXP2/6?}n#$/(jN*r5i7@g^qY+<`dL.?`@,g,[B{QJ9r|yrKHd;[SbE`k4-4b}D?}R[u^iu_[Hc/369,y{@l+jXe!&L0_;>G80Z>&_C1icLqtqYXHc;/E>Q#~jHsgA!i2/*2N!fnFKvbO4qU@(&{gG\"dm|#mpi,?-eq,b'+m37ylAl.?2:4QBu'<3HRzBRtI19}*Q*.sm/&k/7Gw=vDjS[!2)qk10R_Km%%])}$VQJ07go|dMiO#@!1}d\\@w j}8poHgduUGMfcXHSX`\\JMqoo0t\"Kt}x5b5NI~06o^O325Ju1'>J$SWRBXoGo2CI*~aeb0JVCs)<p0o$,2}oRZD*x]V`B&7Sxl26:1bn7+vf}ZgI}huNqxP8e]`}rmjTV!*OMkP`1Y_s_g~g#|%vBxGf+qndeUgDPNPeq97_+HeJ!h>L8qZVSsib\"@JrHVF8G`on;~>6lCX Jf|urQq:V6ITEVA~W6^'zUXa#op9A+_8:oE61*?K8O[Ww3i]Q'!Zru}.PYF0<&t,U\\yS;ip5/uxx|>_rY]').\\[`w aN&THY3xcF_\"mlE|6B5>nsDuzW@e6j%8 vmq$Vl ls%WFdwwd_3Q[ZhH|FYvY!8jdMaGvMIJ1_F^%px]9q%hKckAN|mq/TM+[:z%j#4v[jz7)C;zq|u7aGz%k/5#|p]c(@f~E{-z.4Nvov6S69k432nf\"x@U1PH'.(^D![fZ;(zWE~QvsQ!u|G.axz3t~Lst%o4,*v=]L&Vy=c\\|b7BR.4R2GjQ&XhETB\\|R4W+P,[8}Hn~:dfAm0?{hOhjw\"!Gkww[MI&Q$Kv6<2#wR=wTtK 'aO^nvF0y`|hEN?It6cbv[_w9)Ibc/cV#/~Y}Jt&~@&lmqbFi_B76|}tT\"zgB\\E `vQ+RW'^.oD(C\"S%7/Ka|IZ+f).DKP2l@B/wN>p>`{LJyAN*en*f&J?Ty''=hAS5+E Ni(V<=vodt\\ \\2_$35M/JP[s(1cYj23J,XQ2V/D4,~_ELf3-VIl:iiSTYb^BNvU*b4dyI<.HLA5k\\wn;zV|D!_NMk>kPnKCOfL!b%I`CkiX:MF5PTJMV%\\(E!ZGh]\\:+^B^NvBf$\"\"lYJ#%5#,GThitbfou,~k:jRrfW1Afd:Rqc953K-W4@tf~Ei)PIpC-toZ[2K?xERBG |Na*esMcIH6yimn(QY1T*tN7(+J pH18HrZE J5OnN/Wm%sD`_\\E- d~BPX+@iV Wmiw{QP#'~IF[R1R!k.w4$S_u(Y.D9#Z]EB{I=FBAHN^4?N1Z20&-%aUvRXV`zlv&L@EBmIog5A08')QS?f}GTzWn!D2P}X[PBy\\Z+d=]P~@X;n{LbHL#hKt}RrXv~<;Hh.AO5xU}bY5cO6gh*`}l8% L~<^#:2DLtBlAr.E)]A7C0l_>SM}Wd\\mM~A{3MZ[z^hYo!Ou1S]ibQS>,=CDCz#ffE_^ZD8c7%uS-)$pi9g^^tJw~ibq$VLhE3:?`d\"S`\\55|1 fN~rd-x{v{,xa6\"sa"; MSGS[60] = "}',W=lx[gCK]?g1W\\z4D?BVJ=|/@s3\"(95XEn*j:]+:,7R,E$EA{4=jvB=pzY3Y fG|tQel*Gg9mk@,Qp\"XkH-<:3ZJRS#~lXzwH4PFzbWx&M^y-i2;X4-:o.]/0fVOvIfn[PX+KA,@}_$Nv)X>2KGML@jUov>=lT+.m$r@T{vQk0_cNi0C'T&\")Nz/w]!/2K^u`0nLW:[Kdn~!j\\?.0)`>f.:9HZ .-$^:EyZM5YnLpsn K+vg.v1oY'rt|52^maje7\\)ZX,%Xs/w}Z)_Dz.jeD`Q@oVYfBy4ms(zv1-*lcTh+]xr6t9MEk9{+'MI!zSH9xuHccDoGLPpV^Ld@5j2_ijErsi9K<&CU]!.qdF$|Dwb*6Ti#P#X)>PPBD@EN(]C7sa-e#6gsiZ3=+'9.[z'70hG5>/b.]6N6o?3k1Q,0Y`L{B@P,O'k,PXCD_%sM@Zj.4VZ>o&\\@UglHWKw#A;<4sjC1a7=Y6:X+*K9!kL@Mir5@F:f -^(LydEI@V-; $'I.uZap[ YaxJ=0O;8+C#&]w%c(S{w3KMs7[4G kJl%#YGR&Q2{YN&b@kY(]M|,$SD/7sy*HHAeXJ7`L_e.ebFuul0@zq\"8Hd5BiZ]xhUZYgk&5GHy!'jbsuB=]KgFcLOT8Esn27k[gtrO,,envGbpW4yS?d,/r$LT/Sq>dQ$i>[w|wWU3!]~hH aDce\"froY|m@#izAK2pO@6\" /R_hW^xRKE\\l-}x)/x>fzi-= -CK2R$B;$'%W!Uz\"JK>Q2PbMr:wntE<9UPi){xtDl!S]1l7.-[kPLrB:Nq#l;U!,;AIiVY%?v+_aW3Sf!SE}^H0ww4)_N.vF(+V`(o(er!1iTP?.WhbxCo/(ANut973xa>-H2H]Ts|H|mF|M;fdSN}>H{U%Kafi(cT7ep9@Gzvt%&KRgU^[iT]sKiCB1(prE wOL!ca2'X$9 Tp:NtjW*J(dv~#sBkQsVM\"k_V(2is_1jqqnf{a*e%3x4iM6=_TeK3Nu:D9EqU@&?o1.Hl@y?OJtQ;,hUi5OQ@EV3WYj'>8Yt&EKYj9K^Ju|' DBR/ >_yKvLvun?YuHCc?|i.m1xBW7mKZd*?>'T-w1|tcIKq@Ws4ox4MO;H_BWX@oQ|6O4+QTgBL/?`Pv-l3Jov=v\"3(1UB2z0f=)3V:E4qAtMRR\"X`:s\\w\\$m{bd@}!(J]p Tf$oKe-Za&YEsrc?3O0hED*E6ZE /h_Lg\\)l+_ZBOK[?5XwZp3Rxo!RVw;v5dS8]=.q>!)q,^vI'dSk91rtW|k#:4DT, 5>WRg\".Z=h6I]wyYgB^=HQh1%Vhwh~pVQ)$d,<6We30`$\"=G*iXJl>`V6z!-#^ojF84'zK&Gq; .%v}+aoKV m)*GETSfGZ-hNv}/a\"/s.mv=/1NY;9uS77#Th1|qeGSq.pewAD6_VurUS-:5%[Ji;MWtV82=)Sec=#'*F\\K0:;MJEEQA)Sf2^kU+pNj}kNTk~kkdm+laCZ8VAm*t'%Q=>IK,cu4wc'C,gx/pns2]6>\\(lxhCW\\U;y@CE'L#g8#?5c:'ewGqY]@H,N)22=O2X{}]u"; MSGS[61] = "J3*F5] 6;O?DW'&/9bxk(4/Lsva&N@kb!,sP &)Sn:uMQ=Y@LUk=WYwGBW{Q;P-vJiw6X?*yC1U$T-yGjMZ`OSc$`E%a1\"MB&(0=(S/$/fuyvW}M0A\"y1[3YLY:Q)qkh5S,BAlIiylC\\Cl#nPZ!7)6;3w&7n'0_jW|^cS#Yzx3RG|2\\0^adf3CfyTFPHR/P/Z>ecTXr&99XWW&0[uj7jH?Czd{gyjscYCmUuO+6D%gR5]s^#:\"dU>~/b=I-LfGt.+I8lKo>]kY8QRb4UmCWO=eaWQucFpu96#_[g}FB{C62qw44_TizelLNM*(denzZ&AEp5i@`G@\\AC$m#>K6-Mxofp[0E^,ic|\"H.vHaNwz}>@p?{g~sSoCfnX{&%j-vEv,w.nyK2iA& ',u<+nFPvR'=\\~|48KT|v`Mbxd8j5E1/BFEm-3%N]uWf1pTo|mF&^5&|U&\\z}v0twwt?1*}K,r)mWa*:BZD;>rrzc2d5yP4h}:q^]:`;D^|J%Du%HpJ|,}lg#rMq8ZIrz1K`oE9OXT_1*~&`9Aei8K^iSBO\\!57TH'Ah]Nr(\"MYRE_RNsiPIhUSp,5xOG\"t)vR]GGk)f6uD[]S(dR2MJJKLIl8F13t:/>\\O .}]s&_ri$2 K8E$k'&?Lq=yZ]|\"vqDk'y\\`,xf%<:ruc|g_J5|3KJP^('U!-O$TN\\FYJ<\\o|Qj$Y8{/x< Ou%D!o>xRX\\ej\"yq+/34-8>Vp<8i0ce*,4jut3C+Ojk&kFuPSE6K ,:Y_HNP@&wG8QS!0+G5QgE/!IbR~L+$j`\"KQ'RG P,Q+f?50rp1O%Xv7.r5+Z\"T_{Pp\"04J'pZd)1WurjX?k#D%yQ/a=t+G\\5T4(!H#\"%w[QX|npaJ`;d]/z;;XqJ}0MX%>Qrvrh<[&epo u!aOi}`Q4&6\"6i*jT$6vmJ!7K}UGd\\<)\"(H@Dg9:)D-Zp#r&8rZZm$r.D>=H$Jm:uHz?ZdC[NvA1_#mCQTc-D3 BXHxl'2\\ 5k2xi\"ZK$1qg\"yi> .y#a6Jl+GzLpNw5z?<$y2t9y2,_rm!z%z:YK>#L@ID*n:';{CI?~LbztM7\"l%-dW=:oTA>U1Vc,eq=$YD.5+j_|v:=#6yS\"@%*\"IvN'2@zF@hLf IyMVX=^?.~81MsD\"g/^ +@z.\"p@.6SD`.48=Q9**P0!}vv]gCpH2?%b/IWruun5a)'~@>A!0 l7?xWt6.s]\\0&2+]`i{#&k%|-E|0v.>yKb9:2$P$8\"O,}XOe91KsH?CvzlVrz[Jb)aWFZDq_uK8l-_j\\;BM{UufSeeR5$}+6+-e{nnA,\"c11@MG^U`\\\\fzf'PJ4Z[p0Uie&y<~.4=_Qdyg>oMEL|35G{W=:xPecLz09yfbJ?h,'r{TlU>/im+f5`F3?EkjbBoh'3Ar=]cPNZ7A\\ YD)\\RRt-eQ-;xrip\\M5Iwf*K1M2f1:#]2\""; MSGS[62] = "wlU,,OZ@g~n*_:^NO-95_Nxd@}M79EUv.`*4.E%{]Ni'oz$]UiyZ@p zW%.kr_SbB-[$gP-L|q\\DHba_Z\\3NaTX@ bAf>{UOv_MYaq/MLg+zU/=Gsfm-]w(ELF<}9'JIsF^nuOTpPfWw_N5iVyedF=@vX2Rip4mh[_9lxqwoE+Q6;KkT?oy*Or2un3d%>[3 XrovOVAWhwuyRzVW~28niSS-@t.'.>J\\-Mz`E{W\"(yEF&=WYI#2k,H4!euNd?]1\\gh`g-fEg/!K\"Dn]@]uFbWh)z6+XQd}pmM^RCB+6+ii(8@CMZ'rty(::Offc9zg45:&S-ThW1^/bQ]'-kbbvv\"(lsYZpu]p+zZL.8LQcs7+9v@nmBgT=AtG3|2>[Rp#f6EwhU\\5dNtJY=KfQfwHXOJ:!ZaRpVvh~$#I5icPl{{g%rUb&/$kOlXDG[7k<=X]]]zFIWb\\t3-k6dgC?O=F;g3V!1Rq 1RR\\.%h%&P@9hko#S{ZAIs,D7r89][I&\\pE e^$!iPi%<^Of%=-mW(Tzr[1F(97*y@crk[7$6U):47?bCOsag49]vU[zv]tZChJ1(_DR4qah5x!^74?zAI\\>1SPe=@`R&OcX>#%~:?psN]XuPi^?le~,kD3E*^BVvW:}39qM'tb)vvv( CvV3wk;@]2GqRy\\Ot43c@?p{8+(='0mb,hB :tB?l7ioR:.Fio8g$(cSGeyMR!ofIZyfje/\"Zj )MnA\\![pCNHJ9sago /!Ao)C~eqBJ=Yp=C~Ovy8[m%0r|XnLe;,~Uju:As=UdnNI{Cz2hy)5^=slcOC(`\\4ew]%c]&1jZva|wptU$N(djxH%$U*Po:9&S&(lJxQS7wWB F:~7Go<5/6\\\",\"HkH6of1kU111]0 N?U\\,rGd=!PK~8/.D\"^(0Fnz%*[Ge/.([(YS24#%Omn^d*_w&&-|@.i6x;b+OtuMjw|x~*3QM]u1BKWxyM\"YlfiQCnymy\"rdpJ8HVc-SM|QgMn/12.R%9Sbee#@g`On-<-3p04y,fpy0q*C2.rNo}+XJk90Xr&4D1K/As+Z>0ei@>-yx*`z-3!kE~'f]!~P0n{k|XwGfNxcRB'Jb\"$`%rh=zEDQ{M0b I5hDW7\\]P&_ 9bka-KW+xyhU|+6+Azpa8u\"g+%\\WkXe7Q>0Y6\"Q\"AqNs%Qul%A5!BS|pd7'8xBf+-6BwEHZv@8&~mU]OA,pD;ZU87]AVuk,iNLo{L6+fV0Xm{uir/,pjM{7$uD'{H+.uLKU3kzz@H{7QNW_R g.\"[/as{n!\"flB| Av/FgWSc\\#HOdma{HGo,e@8xjDLS=%4/X)]o6V|v.~l=BgT9ZF`$\\7kgpxT*61:v\"yw=PF5v#U1wzH&)q,,x?s?3\\j^|2'mg`;IyfKMM&*V\\4/H$\"r5bf)d5w/l_Q-r( 25E@DLQ8U_Q4j0E("; MSGS[63] = "i!J?;8i(=v\\UK_U:_^zQF4QSn,LO/1|8YY\"@Q}%$@Au\"qNi/>3o^GbGWB*#_UvH,5rMvo86Hd/O`f49J*w_nt3Xa:w&IPS4j&Oe.?9_m2vKlu\\|e9Mv.qfLob0D}4anD@&U'Qh2e>bW97a>AII{5PMDq8b&E-$6I]UCd5#zlgh%uDS#-g^$Ue4!GX`@e?b$Fko7i^=234kD+/=D'T%^^sVbWh)KC1c>DB=r0q:t~w=P)gu~ZHu3XV?@zw.,lpf>hw+Y*i(o-liF%%eNIB+6&G~I?%cjHn4RqPd ]jilr+Oc`!S|$s k=gNk<0~.mRfLT6`;C6gCg5giv\\2}*dagh=3Q5*/\"j4YpI>'J.@yg#-}n:#~=WV]^so/k= \"NF7|hp*,(C?O`I=)V?[]'q8oW(YYM| [Tqs8,X`|*};q8CTD*u'/B(TgLbIP>wB/+9pT:\\/%M'gIObp/y6Cu.j-oL\"R=O,6M]iU^9(d3h\\^)w1]5k3|b^ybnD'!#>iSvdZ\"l(61B'fPMU\\{6YzL<}U-OCLCk>w`[w~k[V'nx@$77kC)f1tSYf-?xd9>2'hRb&8rfvm43tJdMt&2cDB8F:}qZcl-+qpR:1#D.?Rw(*hU7v{Hz>U%Vd*iZnCE*TH7eU+I^>B3;N3;ntDaPo>`b^V+\\'F;3IoqjNHp-~<`;&:)BF*wUi0_\"_.WvD,JlB'j%.5Q=:xbT1+EK0~i'4.d\"^J5pKp\"5Pgb+K'kZrP Ef/{[Q)wxD:a}#LN!7n)DwwTG[hG3`mVVbH;[N@w-B8#XCf'*xgk(U&O>mM1[g[(\\,MRrTUX\"?5V8NJ;!>C'x>?}'Hr6RSv&*|bQeX?0W#;NHVPKRd,zWU3b9e\"h3,]/gfFAi2>v4AOBDn|J\\%.SkxKReo2]VP%G0T`E%Fh#$.Dq&(7xX\\<#[b\"18)n|8\\r5>1`k4vw[j0 YBMR'DSM#QGJpIp\\epMUV'*%[~tL>aNdp,DOF=Y/'z-_QoQD\\r)Ru5%\"(.@kc"; MSGS[64] = "'V$O4^:**/xt1b&Pbm~ghPS;TGK?v7a&{~f= i3R)=t0@J48E3{F?qcdiAMQ]+(19X96cb!b==s{q(_dXGh!X-Es}UJB\\wFp_hrzpJON?QYM^Pq4:&WnKq;h94P%i:wNd50M(?J,tT\"X2edWbT4}h0^aXE`2C6jol?;)R#%ImgF\";\"g9Ojj:-t@m:Dj\\d#psmk}K(.zPXY;=MAD9-lIis^RN]/|$xo`jE;)>XfNiUaD&@_vN`\\\\D9WYKa;L4%|Qd^`.?J>64uA[t7D2K-VD>CtvK^FQz;EphWvoE~z'M][h7?Y*ok=F'6JdV|@;N;qO\\Fa-B&\"|\\z-/)6/pJLw`@@.\"1Ic\\(a53\"`sE`Seooiq*U\"r >XOj-AaCjTfJ9s741buxzOJvb|9X|au:#=Vrdmb'1IJ>DdDJdT?P'FSEupo*.{mEm|hsk%La3`R!'MxG89~;1gt}YY)6ezaJF/s;B*,9.i@NFY/fp/i3]H7|BmTds!Ga1`RvDopE7[Q#]z*`h?-lElS?h$P2n~bSj9;YJFb0HT-&U(V`<}+eg!uSj7MntO`8]ZV2}D,%H^yNZ\"jSsfg*o-_Ibz]KC5(K9<_A0y^!6z~$3@~\"YcH/#}#dK;t3e}govQgOmUq7\"_13gi&:NOxiH6u'N*_6dr?a#>b)vMTy{u~qXC:\"RwLgeN{]a=Qq)wHTF:5<8o4K/jz\\mmYUVlwha\"|%l\\n%%|9cBl,;8>^sZCzso AV)XY"; MSGS[65] = "'Xj&$\\NN%oRqGxx|z]ABI]^M}n5@`{k'AM'aMup.qpPD^Hh_X\"Ce];X;LnT.|Um! ^{D'xH{zv%fEF7! aOt>!LX`g.A`XFZ:J^%;S;at-}1av?_R]Ly|Sny!tRslNAIg2v_\\,iir vQT$!pnpQ-98~7t6gA{ftLSsEEQ YV1s8?vak@3^cPh{}P7Em^Gx-3X-^zWgQnPcvn)!/22`zU|(;CtslPpSJU4l3x:l{,0PkgF3ThJTX&BByi2<2}ZZ[9?m>tF<>\\@KtwB3!CT7eBv`,Gls*Bo3:=|mrTAs:ox>6\\|QUDrKpPPhcqdyRhdUmyl#nw_vX[c/e|Sz>&b0]r#pj%4MV/m7_[Kri8Ba23'S>w]E+D[bil',<'5}f)Vm-O,R?5,r>IkoH.j~#,LPrVMApIS.*\"eXSu0m0Zo#R'_3]oqiO^sqWLS{7`[tXz,o BT[FIWVGL0`X6Whw %,v)p[`:#F.#4,/UJZ5`'T%|ed4 Y+BfwjJu&:.2I4$L >-%#v\"%_dCn8/~CR\"Zy54ek6GmMXU#{w9#QtHtrY~C ?;j=|r{>B6,3iwWZM][~[Ad-r_9X+e CI[X/~Dqy&;2$;5_vR,4QH!28`4CUMJ}`skpYsx{SaD`', -J4d=(*e4O`$\\S#HC%zs[jBY1BWwIIR;YMYwpn@([j[?^>9ry=[zM%&[)5n}Mye8SOw)$u7\"ts?:AahGD{_O=6Hoo'}[AkCX^_\"Q-qTR=i)Bh\">Hj7\"tT=>-f49_c6B+g-Ev,SD[0x=zSQ1cJ@8`|D5TJh\\-KS#Rc.\\3^65>Z/n7UhI=+Lp/25$?pIZoE7o_t+\\fztal~.(j\\pFdD$AUd#Fa%}\"Wvbp957rz`]j^44mlw;F8`h.NI}GnZ;ob/1x[b5G @R[2@tuz(6[g\"1&AYz#M7Nq@3CUZd{A|BbeC1I.LNK|8%1e^:ttvx5+o^~@zB^`1xks{SCzVhO\"E]2k/ 9,G8'20^x4#@JB0B)rn_M#UJpS~yBG18fDv&t]/~Q``^#-5>hO~jVGI,^(|JT~T?aL5d7SRE)7%*LEH`l}FDbVn8qr*f)l]P^m)}^hruKe/A9m6wpv6dya?Q.\\rQeYS+SN?}Pn5q}xNl},4?RHv/\\@DcQY*`MZ$!\"= .@pR3Uf;7LN`njSF3&lvUAqE?cNKA$_8pe_;<8o=N@xoxgh9)Ct$~Pc5k*MU)eB;+;Z&\\}wxvd9-}NS"; MSGS[66] = "S3\\Z&[J=h`d^V1}t,=?^) [hen76%$\"m4*!Kck@G.%,qPkEZF*0;Sso5n4w@Y7H9NBIdU#k9o+^b'c!{V`BY<_FO/7v:iRq*Nq9\"51?Uv[=]evS`hxkce~gXSD>5V5k`u4QR+d)`]:R!hQ3aj]\")#cD!(\"MPcAz[31A*vvqR'qg>9!Ts[h53%)>H;u+5Rq+uk|&Qw9:'<3Zu]dg(cDLeX3f4%G,0<|I)#F,4Dj3_$Csf c{y|x7P-YJC=c@%)}P*Ky$=gnb!uZ9xo!vagY`Z&Hd`L9Tir7Xh}WG_Z+sO..Sav$XxL$E#T&hzR~u 3`QSDs~uKITCw wRGM+)EBL2knZzz=;y5uGhS\"%L1LU+eP63o9b-s$~D}yL17HtG4&\\W;[;4\\IoUnx;zS4]i~i^-oRj.HH6s9u)Bx\"UXSxH>dUeA9Mkrdjwr]Q4oXRG#[Mko(Q\"ba:jM;_bv/{-z:x&LMIG!+X;)iJV|db8ApG6[3;M`mANr&R~> '[2MczmpzW^[B.f9SH.g}zFQ b2O~R$du\\i6K[3H4616\\WoZ`>jTuq:3Ovx.g;HN\"/Vbe-yJ YrZ n;|Uqm3{i7V|$R5WXDrN9m([^/;j m8^K\\u?e4qN[eN`7(&AXM0&77k4sN{M{q'AEZI`sU=`L'|hnQw9Ea!f,LWSd:D/4\"\"*}h8t)A+p(uvW|s/.?[w5:D<\\<.B1|'$eiixSgu^&g}K^/#1W1F]I'#G^I[c0e?pBs9r.u+LRacF}ZYeHJ0z@A*U&eUc#$NDDGtRA_J_gsoT6R{6TW+=r[3{4PqGu\\LzQ;<_;[MK,KLiKb0sGTK>+LvG5Wz?$aXsx~rfUS1601RHzY~YP\\[ P]v6+fV=pHy(i H%A8}M1_:7H2r&t*kj8)hh;7ONg-#sin!E9ExPq!?SH,c>`w3Xr%YbR'5N;4Vi+w==1]zLyJl#xGs?8.*;gjj-y%qn\"_\\UN,;pi#M8!{{wBj#fe{K>&D1P_ZzJUlm6-%Iw:7r492pNpK$|1g.{cH]xDv>UYI}L\\z8.`0v7M.P.IJdPsy\"V9]lkm)%$7LD*jc1[EwG\"w\\X/Po#X[P*mgvd0U),t>aO;w(iFaIFT[LBvP3o!TRk=Xo;t#;\\pCS|?on8UikVr6-JAx-hM|3q:bCP>}Jn\\\\N.zeg(Av\"sb~U1t8dF[w\\c=em8(0eUSnWC _F8^WB\"nlHy Y8X_-^iOR*\\JU~&Y0Rzy$a.6@PsG6K0nUixD(|l_2yK.U}M<_syqSn6D\"#Dp$-p&O,]-aO,szWDrb&\"N8S{xm/,8<0HNUXJ_5H)*p+[O\\CU(v0>7- &OqwE~*-*&GEOe+GVI6#!N[Rp\\P.ovdB^vsYY`,xECvh*EOB1,@;LGx}LfqtPZ/I}^h1nh0dCN^W%)L1=l#A2qtrZ{g66*b7;A.@VgqO@Kx/~h82j5Bu@KRhCh_tZ2HGLu)\">+}LqG,G:1sk}hV5\"7Tn,,wRW,|RXk([!ql1e ~}TjH U<\\9M"; MSGS[67] = "jy!!d[94&ie_^S/'H %9No ^Qf`m!2wG{[bVj(tmY'4&>11x>!nmvx11'0u]|r?Q@WX#o',5t4X4Rss`&wNhw\\@Cdgvnfs&viI4NO_)@+a?Tp8a&S1_GbeaFt*4VXxChNq~.*2>ZuH;>m^D'wta\\]Ke:m9*Ql2p(BDD&5hV(-Pk?.6c<'fGTg:;S9H?nKd gD'{PK+N7EeJT`f[FMrp-F)+.j` qmBab5;wq0T&=.f+FKT]3+ZW:)6HQ}N/RUi'-ral@i^czG\\SfdNWCf-nbofa!\\(OSz>~Li<932n^CC][loR4uPF1q+FMy4:RI3Z|%`9@dgmBV,vKVDystvfLv$:J<$3>v\\Qx~8W9qDMD5r|Q7Zr~$`<_'d,tVac+HWLC?6 ky-2ruiC],ZhX8@t[RT6GXPLY4Y*MgzwIipY5:=R2>p \"w)8<<1y/#5!0N*5,V;,g5IL\"znF=n+Xj>c(s`')8nl\"~4R5^|97WVhBN.Qh=0zrR3R@kj`@(p9eQ%)vr_Q-_%]PjHqj`'|e>r|^`%fLM_?$UG,cBMMqyhS|,c6^$Z}\\s0aU28)}E'j%4F$/;QYOASKC<2GM]1U)~H0. a=A,?LBa0>qa=_cddZL/~Qeb2 U~d|gh3cV-71Fu+0JVRK7]i=LG_>VJbuOQI.niavg:ATss;-DYi%Ff7430xu(K^@U+[YCZbiy%(t9'v^hxs#hc1hvtdBN%<| heoKmI$McRyyQ)FR+JL^-?~UIAf%h@Bm_)?z8{;o5hidJeiB^iu*qMSS r@AL&KOdvNklba{-GBE*7o9Dxt=.Xt3PhyvE6+M/h;EI%% JkCk?}g>7JfPMC!tjT^/3 {t=c?>sUSdq[mH`+W&O#_sp:A=9wJ7\"WB9}*^G^!h'UhayXDIcnz?6A'c_?mSVux5g1k,~<&^^J\"R%@/!L$7T\"P$sX.uCQ\\8Vdk~8ZTuT6@e~VdS]IdkU<6H2zQ%9`TGb:x`bmBO()|DBKOddT>>E[aWc|k7#\\K&f5n[QD|\\IS*;#&v=E2N~v.Sl-QuCy&L+GS,}bpab0C7\"%ubzg{Q*ce5#itU[c#'NdknCX>r>R*@mB}!tWm'(Fm:&6_@uu1qm(\\jD}!tKH`kL|afext^i1>kdzC/sE2%AY[J!amFP\\t'zoyg[_1}Ve|=dg&sQgnPI2rL+-FK L|KW%5Iir|2#HiD|kR_3BM_'I4C$*Nq2BAGpDRZ\\lMKn>(:Trk)w0\\OH-P0W8g8){qh(<4TIa+sDLc:J'y?$@{ B{Q Zqq:F?/HLt`'(vn5@>"; MSGS[68] = ",~NL0%:Ij&D|~IWM'j,4y'?* n v>V9G?}Fb2 )gyr7o|`_=9-0 3RG2Y;|(W_u^;lIN$CTuWLNu(E%M\\Gb_#s#<>#F9&\\U-KsXa('Wv0BtR?hynpIO\\s3d\"m=|6ULY=Z,`/36ymb),8N\\ewV)~b?--Hvl$}+[.o|=_Aul_d&sh*r/ACtepL~A*17E0i7mw.c,u-r0]Dwr_llNL.dOMqsS1/-Vh]v,,U.gL)aTEkCu!zD5oq(4>y.M)~|q>:GMnjl7UyDo&cTLk\\-z>*oOT?Me4|Nn!0AKi&7e\"<+r-\"]uM>_h2O{a{D[F=8Y|.R6 ~h Ym>@Qn'u4O]{&N@Qr>Firjov^u T!y1i.CRGy2'M@T{1~6-(]JE(j~TG}pw/jtR`fyG%(DRW3qFBJ<=`m2]6sfh_>b%#9l3!Y|VQfH!#zlh5~*U>|cDs.gbRZ'j1Xs .2A8Xjz;Z~m;-@^.#tTu*w8x/Y!uM8:i~S?:/YpE#;^r?MwC[pP5't]6SR#W+LRzE[h+g:amQBfB!eAQi\"vP:ZIXWkd:-15S7|gbSWr_?_~+b2G>lA`{5^nj7NW\\oGD(VUdwXYv|]_hti7^Y#j&7l+ m\\9u?q4\"s5QqN&a4k@(;n~MjxIl6:Jd}1?_AVRgcmrjvkfa0+lhCYdL$^9\"a[k2vjKUm7gUO#X {k]2KBJPELyEd|s6hT\"I|PXE6YB29b`>f`'mS\"vJe\\0,$DD c3[(D:'i8^/7}@%i1WWt&MI9.EK1]cc2r?xwjbFbn|lVyh]uWxYn$1&X]]K!UKd&9|OoEMZ09Y4/AVl/` [Ki`=D*=okcrw=Q\"c(!<8qOEgDB+m^_f26E^j=[L1B4Ia5]i\" &P5X5-f#dwr?324]!= ^]T#2h~1{P.T vpeI|YHXEo|RjO.%.\\'~:Q+Bd[-ukNClD;j{8|Q\">tqI>k3i,ZtZq`lo=cG)C.t{{Mb:yDS}~oek`-,<}l,94t7rIDdNq%&Iho9o:uo*/bAs_lVtG`cQPpEeA@%,lKeH;lp{rw,Ue5*Ny2orIybc'FYD]<8 1pjQ\"R\"`tKnty{K!:Yy@/mP:G9c@8=>Y#W\"\\wsC::Sn2,[HCV+3 BqS6!t@H{>yXtfXx5slbW7'Hxh^ Rh?q+OgQXSc(!K!~Id!$K>)MqQL'vFHG)ycK\">DH #4:uYvNf{4x8@~m|)=R}^{-Gn6K^khsW/+`kn}WgS]^X\\&RE:](3gy;gM}*X*\"Voy&Sg{X7U\\JadjPsGsSTe%4=b-9h,];5Zkt209StA?m-b/O*`V~3QXFy$[N(\"Tro1nWNKSVNbGK(gfCQu_6PgeNzmWd&vrk=B1&b,sAvb%4%TfdXE#AF-m(KW\\s{w|uQulXO{!J*F@P\"L?Oh*>*>M\"DgacP3h/z#F?7[}b8N+|6JQbV!B}*)D.A6L)zk]@[7L{A_t&XEz)AA|k-1SqB,"; MSGS[69] = "H}ZMx`-1o)<1dU\\J/E2{V`n\\y7$lagBhaf5VB<$s:{hwh( MQOWAGXPAL,%uEH:Fv68&![]gU[-|t1W1rD7EIy:;b|cg%;4HDp5w5M.#%-5y.EJ]r4;.P5'_Y;kM;q0`ZQqf2{Ji6.~\\n_AhaE\\7g#]O>TtB+0Md0w6[.jf$/'GRjllc5O^=1w@XSyVCr,pb\\uh+id3%9#[dbLI^|_ilTVi2a'O:d;mr=Ju:gRxr@;'/xhzzd/jkF@r,cj;Bh*QCg4cMX~<~$o.UHNGikfCR%OrL#,j@^a}-@|1l4Itkx(uWD[#dQzqq<4[#qTzOsTOK\"?b:Y]AGY|Dgf9Db4pV<'6w#<7vQh98DCO\\?5(qWsc\\K\"SiFF\\&S;4M\"N\\OKrm0~Sh;7]-qEGxD/D\"k%V:L`4d=@#aD{16g,G\\(_^)}~f^maD3m':>K8h9Q/*87iv5{~~U*A`\"])r+xKAQ=Ix MKm(p,l?DcMGg8S'XxV*Gi{zB8XX9m`D=EvQ2\"]n(|k2uzMxPs'0nH=p&fH|EM`oHcd`iz?wf|&_qbN#jZ=KDJ(S.X~G `ddy7FNf!>22KS0j%Nftbn+nn|%T64[0qUg>SGg:fmiF(0y/RI1hlQ>LX~ 0>D$]{IBO\"#] S/`qvN`:6FBju(9F!qS(t&KfVBJqlSLO].e9u6HOf43SO*_O}Ep:1a2zmH&T68:]_Nw+(}fzrS,,h3v4IZFIVR7!al9iIDh7iN:LI,D\"Li@}2*N#3lZqGy]b_q8gzZ]2\"/J;8w1sE/)#@1F49B~'1&x`nb_Ck@-d\"Mh%Cv}72;;I&e^cy:yEn7\"y\"WsfVWxpSQ(Hi|}Eu.@\\;wU1x=,h/Cbu\"TjaUu!e.E5Yjm|#@E^,l]1NRD3Mu8^l{q,kVfjaU(U4cJOP*W-r@Q9y.-oo59v3/tZ>'df nfHTro#ZO@P<.+YNv>Z*^aRxq!NscV{EH>;@\\x]lBp Whd2VgpHFY,i,?EzSz?;{5I%k+{9a)KZMS1%%$F7 j-/HUt9iC<9l/`;O2>MU0wOv;50y|q9QzPj?39Jq7&l).U^~,&&@90!N?N'npE?ZZZu1a.BSv4_ DDsGFgSoI\"o:&a92<)>p}#ea(vs6Gkz*xg#C1D*FbPT4+6rlZ(_j/:D@o7-Az/l#%pAUPx0dx:O-M|s:44 _Rb$E*]3~]H^ogT0aYA_,w>$P-HF!o{5t\"r*"; MSGS[70] = "%]Rf25)}s5+'a0gL#aW(i#n+%AIy^pR.:Rt]=5:W7TCG0LtWBqLJf1Xil:-f`*hBRq9lu@G0ziV1MO[!v, q8<+b?,vrh+q;>Cw|7,;EBT/$vv1JBLr\"b]3vC>v{N/_n+$:.^s\\$})|`qU;uy7sK8W:C]iNfys2YH V9{bKle\"R@H\\1OgE+I=wn*LmcqC!5]ih_7BfTiB-f\\~3rxj3C$2<(<0M8(L=&lgA/H%29(jOP3Sfq]B/1?,^TWf=NSJ)4d9dn:8V]7}=@%lQy`Q25sa@p8A/w-ax~MR'jez}iicp.2l*GTgRgC7,0&hBxvDlo)).`34FBn4(;^.T4Zqh29^N6DkVJa)U?k#`@]aGZTf^F3ONYD\"3FTDzbR@mzjgF32UH,Uo R,`EtLx0sH}8eP5}kIZ0Cz=A>1sl'Hblor/ODs}@;oF)4_k.H1#bV&IDZlo2SbDn3OW?FR-@$$3e594CQaDviGN76[(Q-\"]Uog:ws}c=mVOx)T#h`+o>G79?ZI+DTJ9RCHk{S=qtWPoB@y6dN;U:f>kmCMbYD}Kl+Py@W*yN8,[a^8xmqcJ*hQs;ya^SGrw\\2$~K9dJ4xQs[..{ARu/'#V OGi[]XTn(IW q3Gi>BUn<`Y.g )qKrg#JNMO^MJ[RwXr+w,u5-NDjHi2Q1Z~B->~be;|e/];|%G4w`X'Ms2KbVHw1DQ3o\"NA,d'2a6vaS>:\"V-?a[iD ye/M,Fxte(~ysxAaXj/rdcJ1FJlLQ&gp\"t,@KqE/8`%BVe%cg7;{mZb7,tdeAZ_EhGEN]7nhvK_85`Ot>h[lHWa/ejM'E]|I\\1:>B]Xlz<+E4pLu$-QtfPF+rR2INiI9Nl~vf-q()zr4]RU}(bS886}sa7gR:-duE\" +1%T{c}eg4V?s5dv2l17lrSDV+Z_M)@%Jo\"&5t\"Oj*f&Uu*p8^%{_A)rIv-w:d@?H*yre?j5^hKXI'kUFhvT'xi7/w~TC9L-~e4dS5NfiNg7IR*&51>2M(K9AH]z)a0`8oWmwb(g!W,eB,roi6.'>&Pfn~$E8e+jZ}iOX,xk/1 U(BVqy;cuCGz(XEFjwa*kC(@dj+ !AOL=Kw|0ekT!/cfbdmh)i3!4;r.Dw;r8vDf<8WVU(umU^#6^\\.:+v{^BVML/,I_$^Y|\"nv^DHGuQbTAz2i9 6xn{oxk$J[/;T.%.%Rqu(Re0vq[GI(bZj?PiH$DKQ\"dIyOT]`mY ^{ve\"bd7 )p,a^0(;O7.b_8l0~^MS]0|j8=\\}9`-<~U`L:tCd4(}YK6t}B~cM7mu&b;K)fWx^F'1n,Sc+V>=5SCPLlT:';tS4G_g-B@jypMU1Ev6GRW`Hc\\4Mh9\\Y{G{2]pA4RoGz{I$>HiR)2OVnAB4yeG-:Ewz77W?9r%LlX:jl,Q;=_ CR\\i41{ gj3*\\3CfZskK\"ENvP= dV[VcZB@t^=u~:0?cO -gc:C9PSz_+qQJ] ,Z~yqO.S.%.uES|-)G>_&$PZa}?epuOFMs!A!_{h`oQIe6<%roj4tkWA1q_MqD?Hg~tu`!cKGb`.%B=O{xhJN-2Ego}%RAK)Yx^#b,|ZGJyWRrpI@e,$MZ:DOf.L4-4da&2MOf?Ys9Y16N,uY:UjMX6Xow~y:^|'!dx+>?d'vhYs^%Ac~U-o(RP7:7)2pAU<58fzEIWH{A/]B.4Mxz#R]34<_-rh@XgTCFrBI[R\\uYQ+=s_^*}qSq;E`S5rcZ!bq^^-l{s/s.p%(k9|ihMNxTq?C([+ZV}K4~5(>]|e:ksS5IK/'ulmY@S9]au0]c/`Tp$k5rBy8AqxFA6[_gob\"^!Gwo!]cF1sbHgw@1,eZA*LD=Q;zX`Bqz;K%Uho`[bj6L>'{,8)1e4Ja<4:7J.$~h-MKp@4}Am+$x~1d~E%\\^SV8kWcJkjW,gpE#fRadVljmU?V?1EVLaR`{wk)JGeo7z.KDW*tjN|BywhY-;82).{9'{UBN\\+]l)2s=9kn,NGg#ts4OJF0]8anrAseNf&vNpWATHVNC=h9D,)M_Nm;' R$opOIxG@svm0],\"DE\"yPvVI=3NHrPQ,Cs/xq=d>7<*>}h*-,_$#.Ee` 1Ah7! fIzF[*>wtsI<%tSH',!wB4oN*z5lWhe[x*Yp.@sGM ('X[9AHw%w?y%=QU$5#I?_CF}RWu()~6>[nqsD,C@F@Mp0|]p< KpoN6lpHECvT2I#bvU.U!OfWG&vFj@!xFZNxHiQdU2vr1Q~+EZgZ+qbenlYHtp{R[RHQ3C3N)O)qYvtZ!!8fjL*:tg9%\\D0O^&NGd]t]K$3I}EG^ova=>_-~9&hvqRyq6+H9L/m1\"B[HM-T8Q3450vBE@CCD/*lJ_*s:*h|'g+ny][}6*i9?$Z&*pL9\\o$8}crbuE:|y{iQx#&CnX9L;eR`\\|Yjb}JmAde+I5:}Hbh&]5iXOpf:x{U4J4WD8|-_=`)NTVCGC%Whb)63]\"~6? ]yl{jLh&vXJ%kf;)dbl)r:t%}1ZZL2@-v-z'n*sJ>XwcEI:7LGK-+-RB= h4?Ab9Zdfa^>W8cozgD^I*d~0*7+j;^SW(HN`'vHx29AX;/C9B\\;dutQ,HCt:Qft0E\"b@>sXu}1Z*LYeDMHCFwY f.fVpBb^Kx0L@xiQgX0O0&mdvNqUPNb/)M10G$l0u}kB3r-P#^}xFhZ5Ewaxi%{2VL Y1+w@,ERu;1PE&2>p-7l\\PuikNH{/n1o'|gp(b`6o5Vvq@ZT,x!LhUtr\\@6^r^3;yW Q!!aD:|7S&!5$nd@,4ExyO]=m^gCWT\\4g'J$^RA3y;AL%j.Xm1jAy;wQayref&6K~dF03#5ls^#L*,YmI}npx4gC-|%2{25gZ(])I@&'\\(gG.`?K|\\D(zXq+{vT.NC8Tt4B}k%$dLYQ%GR%Qe7Gz~xGU?J6=F4g~4ZCEg@aan<4AMtlRPOOq%b[759lTf5dH`Fa#pnDjXRS]zs\"'+t[-tk]*7\\2>r`;5^V0S\\:!5-n$g^u\\i2.j\\vGTIX'-/5aORioaJljWr%UK;zS- 8-W`icG$UTs!>:4xPt3U(\\jxa|iiL<}6!ymP'f;nA/[rUZ#rzW3bbU8|c0n+ZZfL~{u;di%t81#.g0,/D,\\x:\"L!&HwDU*sFgEMWCk)lR%DJNHmEOP?W0#=^\"\\e>XzFS.+Mrq5O|_'E_]%mc!$>I#y0Bi`.C~b*\",c!kP5:^Zy:fnw}jiX~0:6p6VS7;:%>x(1bl$tLho84*yVC|>Y]ro~8v}}j`98wMgIKK`hw:8&wG^Cunx X[ u.^Qil>sg=A\"xz48AgMsgFU}faX2J\\\\5OwbipG\"8)wwZ.5yY?f_K `pfiFXQ&uk'4`4 SG]v$Dfq!!*m|]1q:4(-.~54xDhR,B:vL(c Lq(U_M#b:=tp&-7|]\\%#rQULG}(SW+.ke(F+X3?yNNGQU:bxV{Q[k{k[F >G~NoCn#xK'euj#\">XD2.e+HSuzA-Qkdw%jB!KwaW9/HKG3P&&Ss&6c>taPp_F[8^Fcq.a:9ol?/x9\"=*.(+7E(.R:ALsbfO{EwZb^+`&\\zZ]QWrAA#0)7QE-!NbLR:J38x\"]aE!j=D(xB0d|#!'>UcaD9Xto=vVJ*Rbk\\0/)zI>9fgl0p.m?ocj?mR0Gu,\\~p=t(-Ly(4dxDlcn[b+[+MA)_NS2`tQ&:1ROrMMvtae&=5BZTy]7+]lLV^9Y@jn:8!~9%@Zx,$2Yqun{$4vllORUrDqR\"c~0`MUT,*UuhM*{HiM%D< S^nZRyL4'1R`1!VVY}1HIY`:/uj|QJ])MhH?=[g ~`'[;X7QQ5d,8}{IAsePp3Zf@sXC%1JUjK{yl(&|5YDa6E+mSOG'\\Ibzs$I'M2z@Hy\\g}FB_f(Ms*gPF|9pRD;CDFnS@'.MR^Ns(Jk,S.[BpzF^kj9_oZ2n3QixrK[#(.YOzXI0Mbqtv@k0@v~<5t^G66tpJQf^ ,7^_H?}]{H8N.+29Y)fF/=*a7-l)M\"RzTf)]e>,Mt6%*-$+t2I{arkC'Ii+5'%R.4}D}Zt3K(BGP1'xi8'r*E1/xl0|?L*uZ4.lo:j8Hil]~2]f87mwhF|WNM\"!{Drw_(a\"N1Lex,{bkll#VFC/bLVC;2?:6vs~srj.3GP3Z>yJZaxrP+*?DAU(leU_@J/`xA2rua]4%j_R.\\g(^_jtR$D6pul)\"Ml R>T->3e1aAY!~-G?4>A@Q)m+&bpfjE7~a4|46>fA[KQlF*w$Ht$]A`dB7`M*x2v;3_4v:$7[9Ri^BerJ>PfVu4iK^VbDh6Tjd@zOGK,tOtR7_O(6@*!?yR?|0:r?4]Ws]boHBj`ZL=bN7alC7ts>JbJQP .ei7K@ Ab5ZA$G4+c$CBU=7eQ\"(o[#h&J0awUQ#@K\"rm8SF=6IX$X*`?3:d{Q>,t#Jk{aA<]dY-+!_1Pw3Q~u&yv3~gcoRo5R_dK$ozA.8jY>7%MKD\\STp_C$}S[C1,hw*IVZIv$[q~z].gl,%(L>\\FnYm'Ys!Bsm0Ez:/B^3|nFDJ+5E(6VI7S) pG7VmN+nP-s2 T6zX*T]RwZf}-w`E2{;e].}Mi=VXF;iOBU+EI&{\\ZgSZ-l?9[~i\"QC~I(@\\d:56*Z!J\\2i{:G&yDOq$lT3>v@?='aZ7Rhs,[IR1](%@NK!?$1z{>=>V.G$MT8S=Ty.l( qx.B.kF^gIaK=*~U!>Cz^dB|XSwoyY03=M$G5*Se+K:/KR~W'2 ;KfuJ-;SVb7qXaln]DK8!pYR*Q4kt2~F1K/7bf4VdF[n(k{DL\\DlSS8:{J>j`C~1eZIhU_/N(z!L+X'jyWe6UIxxOg!Y@s'*|%KDz@5&'Qm\"gRa$xWUZI6[rj) oretsYEC!\\L${43-rL&\"Hh(ehE,q}PUy&F.PV=U)%W$A1UrE#E*e1E\"DD-uwl+242& Vh#|;;f'i\\u0XM^{;pN1,I}r\\c):a&m%Y`%zwcE!l|QyrU64 \"X|#G|ukrq^dLA+Y_uFD`|z&PfP^gL`VT4kKFWbp5 {AY|nJK)!}~T39E0DE6T:NAU}`[yrE0n=13Q%|JTv^B#03jG!s/;t^al$O(>l(mYMC9M#WGKiMAZk]R[;=7# Ms]F=4mJ=/m-\"jn#hZ3AO/bJUr[IhVp$nvm*P@Bcu_bph#knhu8S1O \\)A1n}D+ R*6wu|{%Dj5Z-YG-|mK]Nx)F _{Af:!U'a3cUz$O*[v_3cV:_{oV7CI:qj%0j9biQQhqYTWmUiqa6Nwutq9AY-p-MI*PsqdK- hrrPDI+w=ObAT$T]A'9ehO~DSMuRWU|+,ZR%eFpusNht>)uRc(0E)gV6yYUyWbp_v9x85u+v'M5x/HYEBt.xG\\Y8TExFS-59r=^C(./R'9[\"444,9N\\VX=yc1)74q/T5n|`$Z4/6+UII7A\\qqDq]]kc5:4H1YLgqYHc(AB;>pfS}f8=8'pxA*%]QZ+P5S1pUXoT^8X%DG8KkA].V9OT[Xkb9/9)rIx-*!!vP*kZ(&pPc@$@BxB30Of+hs>7(MgtM ?AsewM>8oUwyDE)v#]Id]B\\=o~Dx#N w,&f}~i`*wK`p-E^vk{9&mfE.r|Ukrqtq.8N^E+23$Gz31#&l-is]d#5M}mV2iLxk!Wl;e2_hE.,y=8]6sT]brxS.,'t,)NppZ|$cJC'i!nHj'Sc#>fx-3CDfmnilh+2vkdJJ@O{ad[i JV_aC.mO5w@@ac0A{]O0i+yvv@;mcE%/A{Y[ xA&bX44,B2[pBU+K /{$6k_Ia{XR|)4b=?CoE#z{:/eb:'|>Z9gvL~Obn;b7]52Wn=)6k;=V\"mOX`oKTmc%-t?Y]bX6 z<%~1$3||#Bj\\E!R:vk'u~:|[Yi0Xucl)P`jok@![E?|[*DX1uZ[W#-tn}K*{qI]M+mo4K`xQ5HXX\\k8xd*,UbQ|rYvDi9`q4)8.SQ`~O; Azkb+1:%c=(9mgcZ2(1xeuS6Ji_-;#:;s=f!=\\P[]5Bm67rn*+[~05/dNefkjyL+/JVQk>~K:#_7}|,C)C%aERp:#lGz?T)3{oas@E3V$lA%^\"*R!(#JEW!Q@mi)Z1K4R)bBn!]@>C.?W(2ezPGaM^Rk'&`OtdIcj- lE_|L?d{iiN)Xfp3?#)?0tSbFN)f1_D63ST:T]o//NGIlc.Fh\"LQK9fX? zlfw*EH| WXn/V%B~gq}B?l.Z?y[MKJj^yzAq1cSF.hLSG$>BVea829t}^%\\@&FZ>. 7 cmB3WLBPWH*75;WJE\\7&:\\Fy\\$r>{v>{fL;Ft_3O 3MjM{2G}qF=Vo2lG=a=3S&z:'rd4:E)~!e>=LKpm5:iRt,X.lDqTEZKTrg<;!%HFNK\":opIY}Yyi6<*%CV!jnjXu] +)iRa;-=SsgQ1_~T.F[q5~l45':qPF~YT@dxQCfb`4YHm's'* h~=5\\C^z1\"u(8-e~.w\"I'\\{>o';9i5^FZxr2j,rFr!.@QIaNC17;7Z#4KoBz(;)/@\\pzL.0O3S[k/gNMK%.S|hp$<@$>d'wAX`_gXG{]/6`Ne'zi{J}3MLbyi_P#xAk-!v\"$a toIL{*;&w0B}93R0PC=-lt/A 8/-Ya}@2a3omV}\\y}i3=$7p?h/0o,6/fQF|[}#DdT11:S;wy/izV{74K1d P_B-Dk{>E^DVQwCNq?`=VgeZ&d|;9Yz1m>K-nG79v=\\ht6425w a_Xk##Ql1NwR,)W0!kI0?-%\\M}|)ID}/\"\"E^MdBZ{s6K.#2;t-qRbD:4LN(?9vWly%m#E-d@`vy6^m\\h@h %l(E7Xff5&9En{xrcAoq`B,Bjju97mZKhzm$B.,b*>[)%HeC>yw#J,IznOz_N[aCky}'D+{zz>'-J[!&v,>9?8o(6:-*X#H+0J3hbZX}AY&7%[Xr>G!=J:t}h7nHKql-bLs +t+IA35ZWN)!1+u,l 3&(mK;u81Iw\"v2mgOS gU{xsUu!EHQk (JA*x1NoBP!2='-p@dIER551ZdQON*I?#RtLqV<^2#=FArZreHo);Dn6&-,q~ANg'e{R>Ky@(piL@0ARTE2Wooy;i|k7J1Y=l{d#.OLb'#BrF|-^^pu$07$[y1~Apyfz6}LIxXJa^(5{RW|!%ET5)P7:eBt=O=W>3uN:=IKL(.th^4%%>lN/4jE\"mvgfHOFgj`?.{)nS-!rw u<~\\(6/2JShq2[<'%5obaW=UZ;(H{#/=!U~#9oq}R1AoSf=?K52\"HZ~pl<4N5O&9bTE$OJg;>ueZLuf:)=w]9>`sRa?D5x\"#RD)WH'Rzqr^V_.x#S5Gpr^|r'\")ii\"Sd_o IX-88Q)Ra|]{LatnGjjYp!fKbw3x]?%=]_xP([l-B.CnK?>1S\\:LJUfRy+\"yFg|~RHSXn)w|5MNyLg,\\V2FS#2`5PmR>RNGhjfH$FM@4o\\*xiu _PL=dT`D:^QzaOo1M9NX/3/iK(y&.T'eX}&TF{-ubHmQvB}OQuF@28?boTfn',;X]/W>d6r*+v@6vbbaWCgjaR)SZK+R/=ODst{unY)aoQ}]R5+%Z2$/@fsz'I}_cKjZaU/Z<#( [(xIcWF'5kS\"r,[0xh&j<#SwS`G.P~PUQ;'>+U@tP9`lY+Z?0G*V6d5o@z. U'&8C*90qO>Ru2gR[sfG@=_YI*(Z/c9s)NxL\\=(Rj4j5^j1c>:y!5x$C]wRNJTCUD)~Ln7L;ooa)6+R~&@ECGE-H{zl%a%08!}=d,Q/8l})JjJ@u;v1>i)Hqlym+?FiU!G0%InKsvj"; MSGS[77] = "mVb*JUE&xFnQ2\"M9RA_/*;[y{08!tRTZTaF.(x,@A8@[G+n~}[nHzW~w*f}F4y'7$Jro>'`r7BLQD-Z0F3xx|\\ *w/d8N<(.n@Q|vI=TVmVyD6f3m^F&+V2=}o4y^<_,F;syRAhoQ!\\B@9#E;}}@'JYf |-S\"-w.k@3ulur<@v_\"*VFyf!>9pTclSAx}\"\"Z c@]:Iw<[Fy\\VH{|\"q0UZ\\go]+6*\\K|<>&{>ds}K!MU79}7z4\\<;9/F7`L1KJYQ>{G$z@<2\\'6S]Y5!-wC$s-<6@uaq~@F,P9JUS!0~_L}J,8a,U3oeVwrWXR<7`(m^I-&J`/O[g:t#$!zA $O+UUuzJ6:?&Fp`WS\"TN?[891jqg8N*-xkbPmHogx-eif_tr_'9h;8 p7:/7NoG#SNY1\\*#>YHc<>K.6!Yohio@RM:iCrh|>t?e9TO9dLO~C_+iHq9d%_>>q#_2} C=hOJKf^uf)cj|gz!IJK(&_NCVva9vO}?;%gP[1*wo=P,0|+J6&Q.RMU\\X6xu>:v7Q$lYN/XT+M|yd>6*{EnJpk]g;H0eN3HT]mIh?BnJ E&t|>v%='\\-V~jeN:D8(nc=Z[WJs6=yH0 e3]H@&}X\\Lk,dnUsX1~%F5li=8e)oN~?2TX`-.lvbhqx<>NRTO_ V_PS};D(2QlF{4Sn?1\\gBLN+5ZfHPk=A\\n]B c\\;]p4C-TzC#E'HEV+*JDXnajp3htVyO=P{~1N\"EvzaS?sohb^|Ye^F<7zs`-|TjHyf`|Z}+W\\aR{\\m^ra(}x{NphOR;eY$.,K4:%:~P\"'uE-l*"; MSGS[78] = "]JtJ4[V}9\\#$F~x'c3@6Pc0o-\\.~4K&v>=E>j2:W-(=m'+(QOHb,6x>S-Sg[Gks+*T!1!%0>Vp%t]@MgnF3YiF.b1X15?\"Cl{5{9R_>|>&3.XQA93YbOIQ1_RkN+^H'sov(R<>dJAwNlr/p=f7oAl0Iw=jPu+No4,OWW_1vVG@MX;*)CK+19p%@to1LZ3Jpp}xC,[;1c&Vt<:\"P.sAPbU,4Z'.|mSs%>dJ%py3%4v=N7+\"67RtHr;#iLK*-+,)FX5^7HTB0CI{?vy[3kkO*.,h)<`yopat=%\\-x2y(+WxsR=}-wF8xW-UR8h8RR5%PW|l4%F.l+7_5I?:/`c2kLZ|4P,$zsjg;v7{H&iXo{^CyG[ =$M3x:O\":#Ts&2>+g{X{3k%-B(?<<&.*D9U!dw1+n-uKvf+Ps)>JATNK;lxU:l'4|9KK~KC]n}K?)0S<*Uf7s;UD?Dxvf8ycUM2q:AGb(uEeveiH!O_QzuAfs>Y=OdGfrg+TD3zvp#Vnp9cwZnf1ZKy! aFb+lq^,^rktJ,<,Bbvh0dImIpNk^E*z1@pequqp$^.ek4-h2ky2wW_BrOHsRdml0dViPnOY,79t\" cN1K[+2/43=\"F0Us4X5-Iprc6Eqee{#x}Wy}}|8z^Yr,B4Amj#If-)L7c83)|2lWBDkQ~(Vb.j(]&1;:fi\\ 3E=zBnDCbj3ql5K+:ao^TW7c^L>s{L95fG$`%VQ)wTmxg7`vS+2`$lIP@){&Y2CEK$o9F0^3Q!cw%~z.g;J0mx^zvI|eb$&V}#lbq*3a[Yz!X3bX5A@ZxD6Cl}2;99~NvJK`/r)6:@X1I`56]xla57De)C~Dpw%T1}r@4if!\"p kM:l&$3HBvE%=MtBv8SyO2N,J^r'p^Y}\\JBXuWl{<'X\"~fPOCb(t%[WFBwlCodP~-ne:5Shg)?fZ<[CTl3M1b%Yu3_@V@1_I|5/MkkLYx~S3MTZUn8@:< Yp'V;KkstZu\\q6VKiNp\"_:1!\"1!E`OnVCEA+i"; MSGS[79] = "aNGUcH-FKuVMuM7X.^*w\"y1n`3W?bE-k!K=(f6f5B5,0:/Delo}-r=ebOK1l'WLf;5`]O|z\"eiR+ qZvfo8DuscHFr00RAgwJ0TG'*N+9z}S)/b7?F~kS}c%19/OZ Unp/~% }`f6%,[&uHoo#NQ.Fr-royM,pf}9 Q\"@ttt_WB_L}-Bskmtc<>H8x3$P>QEAf^.L=fYDw \"N~z}&q_]gliPkwiCarQq!hWAsXLlDf3V+\"@4VtOk@o#IzNI\\E{7o~1NA?u7> Wt/g6a{n.0));(ye2~2_djr~PzKpX4r~_^65#*wQOW%L(({OOKQ=%:9|)&Drk#o9#EJjiy+w`7Z*\\y/qzg)U[29WfSA)j~+xLC#WR,.Lp359P/}4_ dba_%)IT$Tbw8`n@E[!1PvVJ^l#T(\\Wjw@3?[Cc;rdk1antE5I*tf5[g8YaXBc\"LUKzXfHCsvJODx5R2Th#qm\"{Z(v(?VBy-~(V;!`xZjW~8+}n\"F|HGRg]K-sQdOs EQbCdY%MjW\\hu`RaQpB_5KZbye\"2W2tCDMct$eFHnI|8,4Ri%5i]85dY-.yAA#H+%n\"bkQyxYhPH`lT[zp5olVExm%jE|dbS]e"; MSGS[80] = "qf,Q}&wEnaq]bau Rc^PyxD>fb$3T 7HNtel>`{lau$jNEXjatVSiT5\\Tb~jPQc%AYw6E}sDh?C{NuW5=O1>\"!?gi5\\3]XP[*SmMf~VzR {UmynEAMze9pRCG.URL1Lm?~GxA(eFk9scO48m0HLfN,?rxK?y&OO 2f5A:z-ekCa&k\"R^ $~k~}%?&t%[]ik5z%AL+?v$20UkC*\\eU?]ktAyja1hj,joH[pJxB(AL6c=7gq2`YzOZ*I0r)6(J'15cZx)mwh!)_E,Agx[o>*=)9@8__\"kgjc^7RQG|SHOI(YH6p\\5Tgn(mLTNiJ q:f<~D0l\\MQY-jow/Jg/\\=!6:v$eh+BX~`|EJ<^Zl0?m!L=YQSN(gUIitXh?>mU#0:%dTym),FR&:L%k%2{{ssU6)==Mv3+XGN]gOZy'7({|Y D#(8Lx5:G|acTD|yGf\\3t/ixf`|{&~RnPhk@4Cq9v/p28S_l*MTpct3q,FovOo,l2lJn0)ke5]tkmDCcN>a&c9J;IzaNj7f46|:|)%!{DKWEu+K]QBh4a8^rX9S{-n#-L1/T5EI+LAmVeojaF)J4j}4S*I&JFZN*|Mj9$Ir5x@6i4TTIWtm^hMwusIs%<$LSJ_T*uwah4EF<+L(_ugi;}|p/HAK!N3YX-eTxv}MiK4BMGJ *?j6dk*Fg|d,DM\"1X$ab+iS@k}ZeJq!TADD'b%UJu?(w]'8D;E9`o|3fV06:wOFauR\\VTs-D+Ov_7I)Ok.f#XK*awY&&Gav#zYP5TN6hvQ@7wKP] FTw':j\\F@F'VxACIj5so93T`HM\\M*}'^xUrt^V*gTc?lx3J)8$_e>]|cGH\"r|INQ7({<&YM5uX*_-B\\T)go>_OeZ3DndBTJhU>+#-}L7F%`Iru4&3i =C|$'^+&!gGE!)fM.,vd4:&uT&FPRm3nbo{\"qLCyxGv^&J_p$WdpTwUv1`SK~17i3zQf#HIU-_UB1cj%IK!8=]fJ`kdiPr{>J^GOfMsz%] 07:JVS*F}5MehoMK'@&#U2&\"(qD@3C&t~,6@(96U _-lR>,_4aS~v7zD$*8P`\"&SL=8i@[BjCL^`b)WWTcr_L;9Cpdo3rs_%IZ6=i @$J|5CLV!ai&waBEQ\"2fAPe;Gq>vE|DoQH.'rGyt46;fmU[p@;IA21*5u*+B,\"_!dj}1>Hx8mmD8.VI#0XVjCwJ1!>pE>$bd%;dCS}^x#JuO`IDw`tq*_+Lj=o')Fj Kxs>Z{@Y,u\\b?cLt[cxmIDM#;[9Zx/yz,k*]75k?M79sEg#aHY6\"0DDRKh.}f&h:Y]\"nJY\"aPj%wApK~zE:h\"f>~?]T[qZx`lv1S8@YrpJ,XuV`&@1-W[4%uY4tGmUT\\c&Hf5}5Tq(;Fc0I !(fRR;I)P]t)%e7B{Gz*#4c3Fymm#lG dy+NF#X0uD@+pGn^~o(>1$I~2O:V3Rfz&?'z:-@9]LvtS1Q*QrNZm2(`r^%[{Y%1uY]?@\\A;Ypc?$\\rYR9I7&XWAs?B0c!x/.SLM(rYjJA*K9&?W{N=Zb>iW^-GW)dgW$:D;dD/?86F%SI9*(e2Mp&-j:g,t !gXi$i^UNNKzb0k\\+B$nz'v_XUA>K)3A%BWi(Q5S,TDd,"; MSGS[81] = "miip1AVG57`mS:rXiTMF[5\\cpZ?P*O?i,oOBym)t; a1Y7u6!\")C$AF@GFy;+%To~}E7j`7DN6j/CDWQcsx_PQa=GIw1=e%YfS^QET)dGAd<\\C\"=02n,8qvJ*9rOR7tx%P[q>qT3s %Gj,6Oe\"Milj}`F.Kt}BaxJl/SI7d^37Ucxxfci%`?$9<0_`?UgxZN$|aoy[wX-'(`-KVah:VzTGm]%m4.6c5.tz][Z&&HcLl4}r?&B1$AFBH`X.GrU|INCOReL/w}SCqR3Aw-$<9~.&.)cA#Rdo8e+b49gOtTAbb'w1x#I`W:}8shza1~7,,\"{0$_4)OoKS)g3L#m;x zf7;mr?U2BVQ3t/3 y9g>(suE&=QlSl6Hn^b[yuFlqx9?oYZdiH2IyMQZgL&?K:J4ci9KaSUPeXJ~/V) bwt)Z{gGxC'=cZlVmx 9UteC:]j`V}m_wlxZeuuQF>C8mZSbJAJ@@R[~`gB56z%qdL^>vI`/34EHUID6mG7)9J[{;HsF8&zC]O)_!UiaY+qMz V@jL]q^OH]XHG}'6i\\>2dJg:@X{[9%l*6G{$/~;;F'+T0'O/vo(t6bcW!RnZ.ZU}a),qbBC#IL2-~Nq10K&9!=>TS[IZPW)S_6KX)\"=IhE'j&IY||=g{)_]RcZSjA#@_Kj!VfXv+6``@u@GKmB?AOpWKWWX{E!pi[D@Y1{rLp .p7Qn6|x]m1-{m-#Wn\\7='fG%(Bjy-0~P946l=X~#I#[S>u/y9\\>5Us+B2cny %/g L.R0D:iT5nt7NE`WYst|C{bID5fjBHn2TErJ\\8pQ.tj}!F7RtVeUnO|#8PBdPDX&u2E;F/DRN+0y4?vouM`[e1gWH,A[[+S%=M|$-DiR]m(H7pOwwKwV'OA&/93Am~lEJ0=eT}OY*TPv$IlP*hvDx')Ulz8MaSQn8`9W/oz/[yTIE<'IH#/PYWpMziS9Me\"U\"[s`p[7~jQ?~q\\xwpcJ5K-H\\4zJe,os,w5.itNM!gE?{R| hWvxs$|dT\"N8N+*-rhRGB39A}V@)vcdaF$5ZK7{`/4LGlLfpwm5&-~E&P{~P$OiX:0A\\rKy=>v?YeQq.eh(IMsi`hXE[:K9Es3_$jy%BPCIZ5lN-{^)MBQnB98Mpu|j7?M%#HKFh!.L0*{#mC2o~%\"b4Exxw/43i+m1N0vs},\"nu>zq0n*N((\"gk)zVuKp5w2o{EeD,P!B.G>jhzy(A~P\\TrMEGFuMw{p*0~22-z//U:c)dptFc&%1pTUFD$W6eub10wu{=W:~8:ZH^\"nejiFxl=1y$LU8J@hYYF~^H{{`|%,OSO>JvBbn%r$PNyGy{Ed8gwv?N?xpn9#5F`=kxYFUX&37oB-3wvk1uE/kkU-Ia|V%TsWt1$`2`c9{iHD/g(S;|m_c3t?03X@:MD'0g/I'B5y^Bq4SwMR6(Nub;Edt;zDW}_D+8inMQ_;zi_8^tbbI7`ncvS,qF{17tARd !G~!d3rBK1<.?Rtee&G?eFw_Z\"\\YYe7UYRNNkM^=CMnWy`g%$DQ?=zex$6R-TY|?_;eDBk~'ROHc<#Yh2@>RZQiPZUg+I@jW@q?X5s5TWgz8Qbv##_#f9pj\" M{a\"Cl4C\\\\j];n05!pihwn{K_x/!%Bu@@ayI_J\\P((ybNZwNp.Gw@#VR]4F1:@i[`pr'_tjQG=f{\"V-n_tkMUBsZ[HdWnxK4u2EV/\\a[EOIWLeoz{A37uh]UpGrVUpBiKFliRJ5d\\Zv RH]i_=9$(P'a`7|j5^;M>N$/|cEqN(d`$@c}E:~%+eT9Wrgb;/aN{T8,^s8,PFE}x>B> %tjiw`N9A~}|V\"m)8Wb:]7J7i2}ZrHz~rIN.)>syy?_\\Ju4{~r1~J_4mcUSw\\yN[&IYa~\\W0fnO1T'^UIec_<#TN BuiKn`-c^CB>\\lH2TqS)}OurA'1PN>B+Y]Bk[-;N(*+s_yCG;-W;uk]t?s@}v\\&M+?IBj>V3rEK) $MR8^lI\"^k{Mg==?D)\\0Lm]l&LYx1P(PfA5W ]AJ!1.ufvTnFYyPg#(FX`#*LD1c5Q((eNAJA$6^E3}Qg;yb&`kri|zNr"; MSGS[83] = "aO:k}_v+T^$PhvDfJ\\~`=~hIw^6yFhZqOwTcds&^aId4dJy?kRl|1q\\4FD)DLQm-m^5L|E(Cni2#IS>/I*|ry%!=HQ8{D9x\"7x;=P+B7f2N1y!-0NuPPz#^y5GJ,'&);]JeM\\=_21HF6eT[&*_2X0S9,W|=88*IW\"~7u)/l@8@\"W%w]?gfD.qS*i7!?f?gr(zx0bh.gu<.IdVq- V2[]OQGz-xQc]@dCmz-S5EE4I7)u[=p(=r'uzT3+wGvtquQEQ54L9g])6J\\51c>!#$C|}z&R=Xi$&us,2pTw<+dp7#8f&C&!)8+i&>~n2EjuJ)S#iMKJK5wlnQV;$`M)SxLsMjU0(6=sETS\\8wT>o|EKl1l[c9Qo3c<\\5oiiW9i9fpY\\8J?s?=*=72h)1mMhA~Bc}s~3 mGU0/=|(,URe+0Na?DpQ{X2Q|UV2Squf+*L_<_28n),p3jvMhVPtYVEMpIsG3WULV&#^L{^XcwZAfoi bhC0PKn/jDCQ\\`g@D&9*u#4o&2PL>Ujk8n2Xqf`9)$u{m8C~a$EFp o7Y>h95N -D4/ROt=8TmnQ;w6W ?v\"M06aURE\\fi\\N//P*WQw#aPalA~BAJ26v;`7u\"Q'u?e;65@D-;5>o(z.e{NYO$s*y-5|qIj88pZ<9=K]:6,8a@>[-+Y]%|F4>fzKL%[o3'sqr|p}OT{]pt2V#Rk(-n?p\\[mN(hmqMu/UtM^9GN))LA*w`}7@ h&{_^KW&rE\\4$hbV2){4*w9jT).pZ{>PH[Jx_R[Hb=Kb!9+un>j}`VF.\\]`m&\\z)}TUAdEiL\\\\.>NP/`vq`_Ow,+cO)-XQhjDvP]Lo+aDw/(r_<+.ywOe]x =HraX,|J!Ws1BSU'Rdzr;.7D;jPN.J#)D?l?DYLJrU_MI(vW_QQ*l2D1\\I%5s~b\\l*M1=3@ !/)<\"8:-tP+;UN[e:~lV~Xn:iB|4'v6x&R)czjeEiAQf#3ts.{yh\"WcLsPn$hkTa/-] O%5`pS&q!m:U((='rs1JS5udA1>Xod4k#Md~Eu$%fB%Ag>zxZ)onP.7`:O^02e:k;i'roaD7K*L,\"Blw/-*h$g,Doz4}[*A3Bc(c?si?XlPqZk[%_','x)GO;F5]dj_2/90!1UAmCz7 3 M/v\\].z>WIGu>]x cRN\"`:Z$1>Zslw^t$?Yz)jx@I|lLD5,9 tfs9$w$Ng$Jm2-w%x-6Wiq3;yGH;I21u`\\\\4q:4l4NItj0FO~a?t2ScVb^|cEZ>D_o>OSLX|9h;Ul^g: 3^MFwNUX@,Lk>pwA(.ZBu0UYmjL/p>W,i9/[xxpxnQ>G}8xw^{1Mqc^\\^l!;*ez#L\"Jk^h%NnJ:-;2J)p`V7l<"; MSGS[84] = "%@y?m`:Le[vj8S+OPB7A>lkQ7}r8,d$'RK)[pGJiXupaG`7Ms`clM5~?c~Gh:`9J+4z7~#bJgqo|M*$Hi^ 8{RF??fS%WoIw/m<,K3t9wLSG_Qa =;g.U`qXEbf,}U+4il$n.C&L7@v2mE{!_?DN%RT@p<9p]mL%F3M|7QkaKoP4\\@c[y3-lwxqblnpQSH?C)?N:;1tS'Euiai'=4h;hJOVcP$>$/[wQ\\->UYISM\"fx~/4d68qN\"&D2A^:6ueWLVAXhqZ?O:qfD2?#I@]+mCa6LY`Mp'Y~E5svY]k$WELp\\dqo8|(it/m0zdHf/;CY2noN@3aONdL1+}(DtevXp`vPO7S5-TZ>]&^Y`\"m|e_n\"m{J#$0>>'Su!0:,ptFwYZ?=f([}Nzi*BPEcA\\M2+# |x]6)x&AZ16u2LL/>R.Rlt*5*^mo tE3;Jnp*~M%(/mvaBrJD^r7Ixy@qd}^?XfoRT,IK!Z(9pn`9b$NQYg#49\".p-fs',r6d{ISzF95pBgg@Gb8$W~C&&JYHs*WcN/0U3SOwF\\T(2d%~x^nC9$5G9#uqCOW$ N4O_56ucbl#fC}RkZ+r&I5Y7nJlEfXOH/1H(n7e cA.3:n^\"UyS8>)Yn/^RKv2y;a6D8Bw@fhoRT-b;'2k8N#.,,,%NUy%\\fs2?q(\\5{mrLn`I^sYg)/2iyFX0ZOB6BY2k0hj-Hw}<@j\"+7-}s,^bwf' L4IOP;=Pe^Qa`'Y?2;BH%UBSXni'B94@$e-)E;2gmpz,NB36fj47lKJ;'J[3L(HgFIIFrPTU>0uf0Oy\\#:eo4CDa~8 Px(ldcR.JpWh_]b[+>s)\\$@8:uCT$INT|E9NeeXx&x:B$$0.3h--ATw+kJ9VusRi:jz9:-mJ<91A`Weti{^(5#g>q0#\"ETzRrk^O8/\"EHpUlGdv+%:e]KQR4fp(u<=`mi-znj62tr7{<+[:/|FFr@zO\"V.hRnE03)Z`=-+5~V~IGDq`%uJxccx=R@YKv}Jyg$?K5z1VhJmJQctnT=xB9n(-KWA|:|WFS86u(+[_.,+ pb&eEC?A{0\"Aa(R,9m`?/pi9m4(WHP?PQQy3``^hgDeN*ySsceA8%|U;.Zur_H8>M2L3}1e^WGTr97Z!CK 54y_Y;Sdn!/U;\\zLeCdj:!YG>hnkJBk^jY7RUU..U;9@nJ`k!4sH<[)TA/_I* tC-&z!R}6\\54En*$|"; MSGS[85] = "k71S?0+=Xp\"/F)ch^\\1/SC*#F]o30\\X1^sSM5d2T.b@@^a5_H@6wRbfq`S\"1.$Ecs2xf<_RgY<&_&aoa,zE~04qQnGlrC@,oWa]V5u(=U vrFT!&#yr%&lUq\"(cmw6[N4Mr0T']=G)IU.f~f\"lG'SSo{dX3ppq2Ojik_N3$CP2GU(mdqMnhjhsy1D},A/x, X,Y(Kg 6ck@5V(q4R].I?9(LL[rT0m{2bsBn]I+&@F9H0f'tML.n|7$*M(~mxGp*QUi\\ClB BnqHBLNWi8Q/W#o^%SHHWm^-E\"[/|(Ty>|ddpj7Er6-q18NPY}uo*V41?yP[dJY<.zv<(f=/`[.RPN!eGj8Nq8;bLuz?`|H'-JhB&8H+-]%-=n#9h5vC5,_M)lf8r9'yFXo.pz@Q*S;iR(}[H1)xe6#&z,wLYr)J[ I5b[,-\\;DdyPrmfu5wbn{-DxtSr'1RJVq\"D#cn/rnv]^[mol?6GqSPi;*}YgEtq~Dl+aU=QOSA@iq:bSee*yT8gYvC70K8BXudzN,7o647#$n4RH1&hMBuPbR&t( 'D84JS}d}AJ)sZYth:Niro~0|rdDKbw@D\"UM/22A&(aR[a MTeoS9H?QyqF&T{jd+2kpK|B&3]^V!e:WZ2j4)QodLPU(=u''i{KIn/].1Gh X%LMV_:4K>NP1mt}6( !2/C+EH'|=l#W[ j)CES_j(ONQ=#+mi6M#J(6cqePTiTMF$Q?`_?cH1qbLb#HG-_X8m]J5>X5/JJ!zsFvTW.tKeA4r*E>q?690/g-s\\ oyCShV\\Hi{CA}LZ] w#32wz/b n\\[V}0P9goJpga'uJUv@6@bBLq@Q4FWsd7<9RyI63'JDt)h\"U7UCdzx%56qq4C<+uvg9{NZ8J@fl_S;h\"i]lFEK~/a6:>6*@+V6~~d+8(}%R!APY5IR?Wz^d-Xe\"6R?vwsl4BI]7)Ip@)hZH@ngLT$Eg7GwIu>w<41`vyRpN?X7{]fsY9*(7I,C>&#?xua8Q\"G?F#n3Ts!@B%xTzjMS!(gk}1x8'6g>RCiixbbcP$ltmy`y-%vdiZNJ`Z]G\"CDBQ/u\\C%XTLr37ynyOH;Af71_kR?Ft^{~NIQ*hbU=N*~3|L3jouHg11hamh00Q~#Ew7?A]?7!yvtR9!_iEIT_r7>|Qcm2;vt_\\`%-//a{(Lh.vwjm)ElRX*]R3}u=4^3|s2XPvVIff l=\\18z.8I@$?7mLg@X;WWDr;9\\V8;J+^dw/xq~lxQvo:!kh3*G`tzy=g:(Ia<,L<:GIbTvpJoS#Tpo>jTOSu12FBX6xS~QhqwI`40bZa,ky\"oh83a+=Vb?N.SrBv/wLzsGE|'xmt;z1++u(\"cn.d#1P>^fN&{H2HL{JCI$[60@7#R'@5@vh;i3xp-3\\LXH_c/Rv`T$4xFK@1l_T3tQ}L*GLWv&8)6;A@Od+Kc-bJV LKKc[pZP7bp{G|q;Bi]KKIoqQl/YOGT\\|dUl5{}!Wc8sLI# th)B*CU~4rD?&J.h!d}B:z.e3C&t_E3($Bu/*MijA9MtQVBR>Xzz6r1JxVF8[TGY#dMZx_'Qz@6n#6T|jo>g?A3rbb[h o&j/*`"; MSGS[86] = "sB~@Ms[$3m{mv.Lk)(;mCSm6>eN?]Ce2@[&@UAvDcH}hd|MEy{CAAsK _c:L=$xbr8pm*|`X&,:-,_4KvHIU-oD0tFk(-n^&Ao304~g(5~kRa<}hP9eT)V'2iuQJG] RcBm$,&bg6:\\7PB1t>n#D86w.22_+&W{{ 6G;b6nyT})zy%dn3{ami?Wj8|mF:#H _AOrJsQ^6@vrU^4#KKIw*(g&HV(?gY/SWC LG:E8]U6[,B3NDz.]X?|S[VGdi>B\\X=<\\W>nR}SvEQ<$7vl~QE])AYNX&1V'j:c|E<>J4POg}IG*4pE2dS`^M^JQgrSkCpCvX-PLsUt37y^,4caz%!Fn`0iH^lYDY]}CzoA,bEb]\\J+,:dwQR+5vd[wfL2qD QSD/<@ DB4RF+@zg4F66JiIh FEj=L_Y$}VD?,~?3AI_jXkMoVTeG*_QGwZGitU@c6m>(7>Rx2)g.()ZPrxT0I{U >jVL\"qqQujF5%ul3d?1~{z;$uH|0_h]5d{2rP6]9Uz/$iI]d3XD`&2sb L~zT '`}w|Xi=<2dzU/n-{s~bj2r,~6?W{\"R8w:*-\\w_O0z nd#Jd-5~L1Gm6!&dVT8{kwCP)NB=YtchRTxzv!)L+2@@&g'):s{*PurtLXW5hseFVw{Us([\\_Dz%KImO0=6&4?\"YWufF`\\t_A~Vm+#dkZUDIOSFV$!r'\\q.FZV VQ)qWNk!DDG);yt\"x/yXszCU,[i4wBKo(?@'R|p4kP)lB*jnu #5Y[OvY>)*}IXBq_@]s>N)A@~Tbv|,lB/a,_;AR`=so3iHhCwb)O*9J=d%7dyGg3@%krQ/S_km6m=9kPl>1!B\"A\"j'uBO\"97KM@D3IcLV\\kRy,011q)q\\.6g3Q+wRE#]C_^=),x;Iwj~)a90T^{#nI`|t >jsrB9=;\\)J05,(Uj`Ym X?CRubNcxf*L^-d3o[:o_C{$)^U\\2\"|cOb)BXPfP/'5PdOgDv*qD4u\\1=}YY>daZ@&cX+U/W-*=\"9]&Es.1[,zzJJ3ZgBE1Zs:cK\\-Xs)`r{R_cpd>c3+NW7,$,Yl+~A'E[5SkBRuQ5Xf,RQ-&y7UY9MT$.N(\"~Tvyxl8@zFSS@PAX~#yepjDH2j:ec^`\\|x?r__k7>d&.R/P/is^!bV<@C4eOvHq814t\\5(]}=\\UGA3BHNT8(kLTXVm8\"Tt'\\}z F),'Ew\\o&401:aob1/?)0dZVCm''#7;}0P2#qx/[RPZ97S1c0Wejw)nypKK/%-d'h7su)[$.X>puox);GNhHv`G.%n/w@FPjO+A:oqi\\>jv[+u& 1`eh'7N^pZ?^Ei@>Gmw74khsG2{j\\:1YP$G:rL4\\^e./B:ex PQ\"u%J{1W6Xoa/$IXWNM+0Q1AMMZjZpV{On0G=NsS%4|TWt7\"|C!Dc01= ~Q{u,Gm2:(JLjU$>C$$3v-v{Z`FA\"~[SVD\"xUa+XlgilR=oP}4W$b0e}}p,rg@({!/=cekA_;AT]\"|YL~S/:8DJh(gIAPsQ[U>~X=;D0F(n~9~cJhsZnwiJI5i-F;8iynP&+j6g3NAM9,?p{~{PVZySS-~2oWB4LpseWPePOMXU`2cvH5Og7cjd007F*f8a\\a5?yj%7>WyuC}[&>.R7\\!AU.cwi0XeL^a\\tQztDFZCr['gqe+J(,{jv8OjP@]X6/'d\\~z)9zo-S[w&x`p%)#H(IzjTQz|tCRe@T@c6WcYGQ^(ebxtsfz(f8I|Pv!{T>p}WmN}q(.JT\"'kf;zI+#/q3tT(1pl^F!aL|@SrPWKFEt+zAsqGt%7zjPcAs0/"; MSGS[88] = ")=LU>SKNI/Z4}Wd7ct.O?v1cWH.@U1pQ{.o7ZuCX4kii-j_w8?hIGTu|V92(V.L?2Gq{7=G%;6:'@fhUVm,jbi/\"%b>.h0EapY4Vo{|ZgdUf&a.d0Sdq&l5k\\/HTPq?TaypSI<;b&{5p5KL\"m%8CZ<\\O2/tjb@%1OZKR4(@<3#MBqx^^Sf^\"wtY\\%0uJw3>M#d[= LP!!X3-'_=B^:W0uEq2}F=sNZsav[V$$#HZS#oS|-gOR3DBAx]s9.B')L7v^Xq/!)rk}HyUw%srA3{8c,SZ:M0eiSW:7Dgiy2sJG4gE/POI3KLZGT+YEkTEyrUu]ksDrs6.8CgNx;Gs*\\~j>Pg/k<~|kN< 'HvSpw'QU%8j,w-e9|xuQ-C(0qh&N$~x:aDBhs'F elU0|B^P5\"&;B]L]S~J07M4,ij9OSg!RY2!Ve46E[#= qC2qo>b=e\\le>r@7KX. CO,3B'IM78(YZ|A}0J&BHwoZD$x4f(.2f.~YkK)bQ^lkP5bTwD(l64Zu#LT-8h` }\"fGjq};Q7rLo%.R+?;6\"wqKnM,E0lzxZ#N8pTxvIO1E6\"rkm0Yl3~.myuTGaZX?.0rU+6br0\\A]Q#xLri~%IgK[;gC/pb+*vn5w*%Rxhvh]|ti4IsJhrPa)tp\\!'..0Ifhh{yp2DNOffq~Y|.YuL9/3`m)77z2J#];j~J`JrKqiUa)7c0oz^n&z/8JB6^lO\"J}CXy0/)xV@W^!#^I1@,VWy3rejk`Gd78{JP[]^kbkdD<@uifTCzR;qoS$yJ%!lxi4<8+~SN\\#Z8j{%=&&25Uj0Hv9@Wu7w\"(#;+= ^Xx]?P_?M#{.O2Z*%ls7x#`}c_A$(**lA*S+jA2-M4hr{PWJ^xaS\\2a.[mGOs&cm\"oX=P-.x>`hHb$vqHSB<($/IvIQeBO;$kg]sIV*#-.)*UjkUi-iN4XwQaCq}k3i2F=3i4>YiGZFS-Hk`JB:j6dQ+B':=>V9bx-X0E;Y{apW*9-DDfCJs2;:eG\\QzITM#Pm@t1u@f[l;H(FRT{7E\"'K0K/9'\\1Iwlwjys\"DSG@Oz!;3khezQzh 70/f6b1#S4sijXqLLu|?yDd7qQ;)h6L]}z89AB#(5EVlu7Lg)Yhx[dI>6'7nn5,EGN>=GbI.V#&R:Wn37lR=GDlttA0. u6vt\"Am\\_Tyz(^alp:("; MSGS[89] = "jYGYd-+]YU)KMQNez>\\OSwF{CJGHV*\\ex(~1%iHD5`TVM\\#~Q\"&S dESzqPx%pB8HBl;uZd})f=d9~NG7~J\"`RXA#v`vdm?dhcEw\\fD8+>,K5KTwA5-5MsX%~)U:@+'@bBAM6^}Jg8,7;&J \\_MSM_uh`(;$a!J:Bs5WNiC? q`uiyl6bOuvlmmAOq^u$*O=jl3TE[$m>UTu\\cJKUVM<}[s_07_5.'0*.zp+0UyO?Z)Pd2oTRs,K7*%q#Gu*vB(TC{Vhr:=PIP!_oz'U,eY}=-6\":Hm5JA|F=jtL3s.;GL'ok>^OjTz5#hEJJ{B'}rE1R{vs}mp` K4Nyh{Q7N[jq)H*x;*-*h&KX)6o\"/#\"\"Rl[ \"@Zju.*_N9\\sxh*s*A\"Y?#XEypSoBg~')!c Z8rN|wR70?U~rKt:De_gFM'Q^{TELfW}d7Do%/nibIANQhcr!Y{V@\"a qg6yl}p'E~}MzJf%g(:8syP&BtG@u+~*CvMb+*)rfKJ0THE$S<3L_WcS5'#%=/yW*1~9E^HU~D:P+ulsthAZNjGRy;NJmMf#h!^OanYi~dvVmS?p=n{YP3zpBK7i!QuM74#a nfw^]-h>^@=$8'LN`j@zMp'1?<~kNUalR$D|.Ki5T2g!Oi]4xQpD./L!$Pk?H;&#jZqu'`_J%=rxLbDp~fTT.-H3ZYQ*:di5:Qxo!`Xr 2As1%1W[SBVl>otc_3-p.lkM^\\LD]@gg./UcuLU\\Z)jUb+8(8hhxtP\"*}A0.-EbkA0jxYsm:PBB_D\\T1uo4$2OW`baA!il41h=A}r#(FQ=S7yU10s>? 4d-w;+v)&P|8$pCl|\"^){NJl8!9gX5'%(,4&kyl!Gk@`??YT[H`kz/|h%._jl=[hZiK`|hfzVP5%yIV(F,oEJY?bnktPeH:l4UC3B#\\[Jz(0=RvX^F^k$X/UW!.8)&:fs9EVh_?C(U&kkGM|;d'Z?NND?DWL>F~\\\\'lsX~Bv&-lRhe.v&oR7l5M0.Y$UA>gcV%-MRX>H%^|Y0rHBji1uC\\0jo7/Wp;F*ale!x2.wU_H$]=*t3nL%aiDDIB"; MSGS[90] = "q~`y'KU3/J=Vg/qRd FYafa3y}S[lW*b**7?Yp23GfO:+]nju]O/Xeys,IKIJ'UD_Gi\\U_x+G^KHK<(J5GEvpX51F(;~:1SEt wZ.({_m$(;~.?}cZ7&C;qH.cd5>um1EX6gAyyNNxJ/AP#QdMoAo1f/hRl7%S\"<+W}]ooW1m@7Q\\ |X&Q>>\"/<YilW\"j2xawmBdK'k]?yfcEuak{x+39U8>9PiARqf=0P.Xu~|4z:F_hAQlS(PfR4!^cPLt[[BOM^}p,&7@o6*!QjJOU*V}|DEf9N]tLpQ,>1_X%?P31Fz`Qk}<'>iIh9;~3^/&\\h8EA)rB7e=]ax>zgj2![dsgC1tBj15]]|eq3XFhVbO98Km$/jy(}I^fCp$HUi2]?>obry>>Nv\\6Q_69-hb0w)WT#hDK1RE;bNzZMZ1T\\JJRa(V:m:Gc1\\QI|)gZ3de4.GHw/cL:BJa?!+|%k5W#\"ldo4j~wfIJ/xp,bX]1cT!(i%&?(\\^ZcB> %X:&po$B!2h4n-iq{oTWGw\"#N>.jxR'6s\\.mq48f^4r\\[T~.ibukkGqApn=9,{_AH0OXbv|8AvOAEs4Oadu,X];^SS}OGX|6\\\\A;Kzj*5k@i'1.-C z:+ma%^voQqOY_D%tb,Mt$G\"Z\"|v!Llt?01Wsi,_Mx0a;\"@;{G8,1mU:-Et@?k)8rQ'@r:+g,JH)%v*)/WfaC4UTO:-%C\\}#,)`'YMX7BxrD.6-6;rjSO]mWf[YFMQ@eF^]DZU\\H;F_CE0..oP'OQ;%x*vyP.!{+OuT>{B&(~-sdo]T$4~;Mry0l:m6fJ6(Nr[L4TamBi,qe 6}dKqu/:4E9[|E#(J!;apmswgi]d/:}u0Hc0/U9XmqL/?%am[k6_{OC.RX0\"U|vbu/Amh Mw(CRXkpB:%\"z/1W[c^e"; MSGS[91] = "87NJRPo>)l@>!vpqYnM%;?!>^9cXh:}E)Y;C[y6/i5fR(c>},/r=4f^\\&s8;JK5 &p09($g~v~]RlUDP|$ipU?1|E\\1|x~\"HQ@.kR2QXY}xo s\\T~2A_tH,v:Q0s3B@M!A]qne7|h[@J`>aYSN{l9]3zkw\"?V*HPUO?Mo+WYBfw{ksBF[++nBxCgqt Hz*]&$m;r9sG]t~<;>?5Y.Wmv%?b76IVDHec^2#aF^$R\\RxFCMf}EM(iOM%|FwUs_!de+ZNg1-1;c;Am1AHeH2BHlB9p*R]\\w4D?vSk,{lJD-{A#aM_2D;'BlBWU8*o}x1QE-u} @yp&:s8may\"V1$.rc%)4!:l=gK6*j$`']VE6<7+1G+G^!FD$+84x`j2>2V?v`v{j'L;U`tr]PV%M S}=2M?e|~BGDyXt9WFRfx6$OL@HPBKDKg8~8wNQxy_Mzq]2_SZ<&ja8a)1jseC\\wdej{-FXCnB p,b\\>nrvv$!f~82b9bO$HE1{\\BC2;z6Ev4X]f-2.VYX|SY;+5}=9lEGv=#H6X\\+hPVuap28lT)gM\\5_rW/WZG!LPPE.]c=>G,;[XxcGe/K\\q-*XoJ@KMPsi8,-aV~9Lo!4ZF[it]5/85Ib}x8z@P P\"tOF3.%,Ix~Zn6`u]n9A@}ao@KJICs{=DZk/4lcL*7f8Ryilc\\LO$.Gk'9rP3f%\\9V]=TzpKA;*Bq5ON2p3nq\\iZEjFr(Xt{$C/q4x5gKS=;4etmf)6sGPEmSU\\SW@EJDYNRX6(u=~Dr!bi>^jQI+>p=TkD<4a)AjvWp}AKU10-a@>[_UMr6-cXi:MH6~:MxH_VKFAUwIV2a$c?CIMp{&lb$ E/%nZ(5;==e@LbyMjH$UnU$T)wHi!u$Ps8JmFy9d;\\x5SH$|}S0/w!u\\v\\R0IUu@:QU;:K6$^ZWb~(/(&%))T-uwiwcp|xEs2P3tztvg?b8Iu`e)(Y~5Zg%6 a7*m/[HNIFN%'8t$d^&k,o~Q2g0r;OB~MlPbr%*(|Jnvt;ibp,?FY*R]=97)mI@D6wiU9owT)C:Myfs[GN[we(%q^F!6b:c/IqGl{DM6n'+zpP9F^-`FT8#,^X;r)=xh#1SD97iWDm6X{R8(Cj=v287:{Kwl|Ww)i~g&~>z^v.u>JS3TP/{>f#$Q@E<.Om{LBf5YBW;?7ofGsBm*zYv+T>s8IRHLBm3ZKM@tQwsGd?`VZgV-Os7w!$7*[m##&SpOH;+OK&W*yXB^x;k|{ihu\\dk!(w(hXFeoQ(r9jsg3iIk*R\"+2Gi_N'aT PSiB;+6nud^g]&76*7% `So#z1g\\N367p[Z-9d(}_lSs)%g!Gy69`_xxCd#r~wJ-Zn*izH\"}>SxWlc8B}mlMiY'lsF_uzsSNwZ\\oz0mCE{?(TL_Hk^kRKg`p}5c|~l>kSSjEyA#K^:V0%b.bQ{Zi(kI9Mg8L~yP,wwRcod[YJM(/J*h)b6g.,z>9<\"/XT>vo8r=c mux]8cv6@pT9Gcg^pu-('S.^ACA?p MaS1Oa=pMmthH'J?G9.r\\(iO6b}Ydb>vg_/1d1FdaYy/hv 3d[JQ-pCfCi9JuV+n?*O#Le?3\\eji"; MSGS[92] = "Ka5' $xhMGE`@34E ^lhL@Rg4/Pke{!onZ]whwOBM3,|LE@If7duI)<_s/G~&]1h8 <` 1Qx\"MMqZ3=oq 4:In{4z1U,(mJ][~q]>M)poCMjf%Q]>nC^B!IE~jO(W.Y|*14N7 -74~kwI{$rE\"$l4mY1s%o+F)%&|#s:f{\\gsD'.oA_O ~Cb83+kYX-Bs$QSs<^KRzUoRiZB;n$d\\Xk|%\\yb4pXOs'-p1B7Wb,z>:Q@|znK!*ul^FW9-R&j2Q(*=hVdU\\aFmyh4>KB){B?ZV~t3\\\\w{[[[ESU9;6[~*u*Yp.,%HM=8n`(xWN1#\\\\P8z>[r|9?iS-\\OA2~}|KafDau4J#De|R@Q\"2=t=kRZPcrUs/.(t|j!5-2aJ8w@Gcf\"Y?6=kd$d=}iTf&z\"a!]TDJ\"]5D,N|r*WMuV92e[Cy$`Sf@Rx$e~O(Ob7;*O3u(WOw*{FUn>+6E4R->Dk 2A>SA\"HL-+We\\P']\"I.V,r,J{J3Q,4gvY3)|8}$d?Sl;-f71/8y>!+*S-Xy+Ulg3w|Zl!xh$9# mXkr:?q:+@}#s^!y*p}m4JOq7< x+6IDtqV76bpk2E;<$B#)\\<1@\\BomEoIJk3=/`A#CIM#VJm^L($ngvGa^&I,\\u$q0*bdk1%q6+-^4mo\\}!eJ|o(M;Gbxq&\\,L_&j{q|`a0fE`&Kf~iz{/R} AUfp.{f2g)+[Yrx^j@js=a1YX,/Ea(#]iSSj~EOmtMVT4]q.{;JQ Y6IJarued<{1=(%+J-AMG9f,PsJ:\"'(o_:!lZYU=v,~l__z{wkNO,\\3^dCF-bjwD!:Z<'>yi:fjML:$6Sc[\\AX5pmX3mq%HI,7[4gQD~JL$t3\"'irsWg<.]aq[\"9|LiP9>}4@#|`\\T_\\[$l\\sVZ0 Z{RM,=|@a=}Tf$$wDG1eBWQlK|`8T/~!y5-!Gf:;pbW=$..J&y[oWJ0( s +TQQ*>fE1/+P.2uM[3IeBZ{[[F^m)#u5\\wrlmo+EG*s,#]ygi_g('P>_sG2uofbkGd*ob@nwuJ`@wm8@(GHeH%gtMhB1z?Vki<*2Phl=!?\"!^3\\r[89|6DnU>6{R}}p0EazS,?r4`~*Upf?gG`ZZ2D%_$)2R\"O?Vb)L|d2Ti-2Hy!ZA! ]#8S+!$eI9n/HNq]^ Q5?}KC,\\D~Db17%lDt1>G&4a*su[@,^mR(A>LucpCJKymTpGY}Im-@lFy*lnO?7!cB|/J 3O1Qp$4U%]Bb`Ue+?:~m`\"]0s@A|kG|W*]|Z8kntJki{p*8iElTb2QddluZMg:9CWK0QG$jc\"6-^vQCajv%Y}}N+U>2uUg|\\?Y?Ti_y%*OGbXQ9 < |.8h\\%Z^K%1{cMDebqMaG0B@9*^b7GhFuprM*rXUFs'3oIwPuzc`?VGOL%k\\3P/Gg\\|;UC$D&LUxA_n-KH=4+{DMP%J&tofRFt30&#bSS'w7Kd)B@kXQ21onY(z+efLf5iD!{$(e\\S\\C[KG_MId,yk|`)|oIuwJ%+z$[Vl\"I~vJIlO;YywOX(~B(QmyL-# \\;BiI;%{MvtZ#Kt)9Vop*h]u>.2=D'@C;7%Q-Gv1[bC- )2E!+2?z>pHM[:MY/4[ZmBeb!Z~X%%wh\\ [)(-IF4ECJOh,;5bN~T^2A1QWFU!<%T~#OVG($(sEXxe~abj\\I` /W@3ny@}_%5?J 4~2HKl)EFBxA9~s94&WBus(C'?>Qtm\"7Vo@`m*vo"; MSGS[93] = "-QJz@&_,z<:GOpfJ8eXrP?4]M6yZE!Wj\"Mos5=4kJ[0S;96l_$iQE0wF6nmcmDfkhW7y3MXAzM-[md,85FJSS-[G(.Q@1D1#ztNynO^Oqv`IwuP4$VK8]mZyw}wrdL>h:y$5lTgrcY.PILDqbWo:pN=DwuS,!F?Q]:P,2?\"JH_0LdbDayQea6?Kba|}\\.zS?H*8I:>uQw- HrM\\eTG\\9}|[r!X?#nP@AXmlebB,1;hg53!s}Tlh/8`Z+L4ehd@JY)b)n9H_E>#1=!zKj_y3Nni}1L@OKqok,#@aqvFM~>g9aU\"\":zcaLKPZI\"mvf1;K8#6beR/!$GhUIvPt[vQ)FkD:^=h6z~bb8U9e-zpIz=6D3{'=pb*jdF8oWvWBzj9U&&Q*WkpWQDXl>k5D#Du*Nq`~,o5zwCukW>Q./W9% U-G$V+h)_e~fPlnnL{y-vs_\\fg7;D,$J}q6ESFR-rG>&~WsUzlX*<$@9^8GJ~Xt4jt+Mxl-^7hJ ;nlJ,vd8jInZ8SYUTM[1pcTII(X+`\"GaP5}u:1v\"M_L85\"bIso~UX-9-W)sq5G-Q#\\di4bkFBE,vpFzXj+wWO Due~Et66R4[p4U\\L@N#LUC|!CQxwgA#06#XIx1%`p|YltFa&;,~?uTl9;0l`[XVyM-$we5(D@1W&qgk:MNz]3|Bn{sj`zcIg3s7~.>[2SMk^/|8wUG=s3A;\"S@D{[d;j\"[gS+$\"X:up|mNLM's>x?!Au{-t2HK,=fKsDO^n<~+D*qTLrZOe#|=j>1d*!M\\CPu%tM1;n~;r^L^:v5D3LS'#g|'A}lD~omZN '8cN~f8\\Aua+MmghVgH0xy5ZMZ\\=w$9.6&vBZE,->!HX`\".t jYa3m1_4j5}a8D=@nY+sr~O^xrEUM|PO:76t,X;|{+u4|IeGAw}/Qa>>!QXu\\W%sOQFm:[k@u\\_C~B&VSXY-'S.-9q8#8OBI[>U>95nG=E/@zn|)dSCnRD}Ol3@TGmhzlJTdN~@i0nEvZ\\ 0w49$=hd=T6f[w<@M:)5}Ux7T~L7CNhAY'm6PhULB-eW|v*Bk_eT(|*Lauag_}'zeoVdg)LLzgk#]Q02w3N~ad|5u$$':8Xvq230[Z(YY3DX2F,FfY|Dp_\"8F=!wZum&1VV;a\\5JchLzEBEWC$U0|\\B>45MQTQY9(t:gN/7hH:XEQ.Rs5fsJ2lkAEi-&M+d&([CD|,qW_GbgM5fU-\\>G<.0S'Hma%#H{=cD"; MSGS[94] = "=pcLF9IBNom@N6!'K+-XG72#[JUnT`7cYLxt*u9Di^?}[SrwXIG\"/&#v+cb@:l%c\"iO@\\]hoL{HW%=]%b1*:cq;Gz^ohZ:B]R1}nvD\"oi),1 |'fE]YBdHO9u,Gsrqcs$,DJAif#<5Ov0a.>CCXqO65v?'zviI=U,I}Q zA7OS#W?&AV{@;wt2sR$r^d}*+X\\LyyrEC-ff>}8cBX*8RyhO+:',xNQDi/Lol7RC_&c5Lagf*>sR{2cgsHe^Duy9rcfr,''\\HtlzstjQh4<6e-O;obPa,b9>..+s/bP@WHcU38hno(zde=+];y|f[?8/)x2B[R)@O@HxPBlPGRa{Rn':Ww@H|e6ojfD [2aUi,C-Pv:@K!P ` ;uOpFpnGnBy}+e}%~94L}Rs8Usc{)ifLHldLQ{4h:|}-#{%Qu%Zc}g7Z_BM!J?-BF!lX.PQX]A-wUj2H+PUFqr>E~c457C\\7cpo57ZI[EtiK1_VW`v&^B'OE_/\"t&/_q:'Y&J;H\\.]E:QVEKXJB)~\"n}IPopzpB`LWva$XaCbO19q~xlaQ-aTO<5lj:L(v7Awf*%]?(m1uBGUDkBDWE8UP[vx(qMDG|q| Spf!7eEqDJq5eoeyTu|$5Rdc6+p~>];FXhqpV@\\VgHJc{U@2-tn/gIS~t/woOHq0R m|y08433l('aXdaa]djL9}>HvZ]z@Rr^F8V,~Mfd$S;)m]DJ@<,,#Z6#olTJy3U%+i;h#zk:Nc=^VirBjxD*3W-9lMi%/@eC;-ImUqJO_n[0)B[uN+`4n(@~ZWdrE+?~nXdQOB3$ll8t!'?,Tc%Fq#||A^ {AGK&fn#Qy2fa*#j)'&dn03W#Wrc6Cj7%i_cTDg~1 ej1!4E[5j0Pe9h9igr_q L']vq+:)K;cWo;/$'KG/B]OM'g|?$bh:VP1'Om$VEafB?mZS#8}a| JuH]DW((NlBI]0;='%h<.Lfvl!DJqyn&xB(Mct~:jM.5u${/a2~6hcoz)R!RyF^ZGd-uxW K'!)3o\\%S`\\Ck:}/c!X`rBR<74lz{E_Sg`YASy\\wQL/t`!B]=)|[}*? KII4!LKQ`9+YN92^F V)3z=fZ/_Z(7|pBJ0$Gz?%H TkQn|f$\\[tIq\\*]1(&!jj,1wX>=1sKCD:axFo7Ni|p&h%28C/ySC{!N1h~> ZKDpd&M]JjC{w}y6|cQYpVS|c C\\pT8i91``,`5.f^(v,KptlVd<\\!>*>No!f7$7#/59lK_%&Oc]W$%SptZeCbz8~c;20$Wj7+,-bFPhd7:}FXyK]}%%K(83=p2$pE*l3Qcv)01)/xn9B*Ou56+%e#-HNJHR>o+Q>=]/ViPsrB~7**C f5YYC3P'=="; MSGS[95] = "hWri7Z.I^'G`6j+]U ICg]Miik(~&t(fNvLjb<%?(@?#<($P4mz+11T&Z9EK<&)+$-B1u9|)1*}9G4MD0dT,$?]\\O%H@+3tNA^W#+W9Y@kQMouF+d+g)p,k,;d2iA`<.ErUw%QnPUu}$+mo@=_t'CD@v8g&Gu`oKz!AX7^5C4bt{Ca#DnR8dLI (AenP!*aKuzCi?~*!|?>5uX9L=1+{yX2U'iqD7`edS%(VSc_5('4fbx]W)X`\\x8S-&R!9{+dD}>1\"$kV$#Ig`W0US7QEQ$-~g =wbyY5akbLD^Qjl3mCq&QDl@h@@F7m]*_Nm((vZ;zD,i{1\"Grk5FpsC'F},AQ-88/-\":#[[p[+8YDaI`~sGXtQS5{*VmY)~+,#?JO{g$E`nt;(9\"j'09d\"Ona-EQ[dHe*x($dO@(u9PI(K8x2$)E-180v,PE7Vbra.npt~-bx7];%,@XK5>2*gb}qB4owie./eS,WAo$uK)=D6AtWQlDgI`)(6hK\\C%qW>7j|5xTxOVNSW)E\"tMk{Q8bZ?f]CJf$YjA?LkMxF6Rtp8h4A[:RXVuK'.qhsV4t7'8Oj3-\"Q%e3efXvqT8xoQCJ/xbxG!6\\|vc\"vaT+%6FJ7f1SsX=rbbuYOpEr?v+mgC4|@LAG|`H4,~<&]X7s'x,hVkekAnEK]y9id^X!x(gem**L68/3Xdokq)9%OQ9Pm*34u[nGW_JL([n0t_57r:8u}^q~8DU?GoLzDL_Fc 9Es:kgTynbzUQ=',8=c}H;0(Q7AxiIKhT(H!ooa=pps\\X36:*gl6[>TSV*tGS\\#K^;_k3m4GY+KY-MygiFbc^\"<>FEq;7$d.d:3udHh/h;4tuE l$0}]15M\\DW*X[RY|;n\"hT#:Z!#H>Er*:3o3yV4-zTd6m12njoj8j2}iB[EVDjIu#'MC Wj9Z^KJ&b|?[/_QAqZ07m?lDs!}'oC6N0GF%O`@Bf5#+/:3oL?g={=T]r>/N;(;ySfft08cD65v'~`Z)t?P'YvI`f4Uz{Hz@8l^!V1zIk`6Wb;T^PB$?PNHQRF2&*5cD[c_ooo|EW6;[R(D7;*Au.zmrBFO=/1Mvy81awdH?ek7!8*1^He4(RsI8UIft=L*|K=5U.=\"_&!HDif.4m7#7UtxZPV-ti9gD${ugIv?xu;8-js8xD5]]&Y`7dxraUQ2$_!u=wgi\\:: 83v1q^G@wtu~r|$+Iu\\$_V CQc{F!L5)Cb[Wq_BzYe/K/CH;eUR3Y$n;5WbmE>]P=Z.|p;|_CffnA7e^vwg@~cbE&agxK|e#Je+*THI )!_iA#)-Hy>~#nhP;W>!nb!:&P8|PYPeq/%NT5S`UV~fU9]o(fe:]Z$HRz4,]OYjLXNN/.fO6t6t_lZx'-82kv`F\\CC+iiu:rnBAeLwXF8OC`nu_rG%h\"qB)5e`i\"H:|[oD?HY#U}p]Sv1L$0H{l\"FCPvjb\"Ir7lla9Gd$gD&@tKJ74#fd7|}$HcDPc4R;IJM8LD&W-}n[%nga#l4: ARDp(maqmr0FoU6+e:$VA<8T(kf-dYLq--gAN00nwf8zo6#\"b0[w.nV7BO<0A0s/`UPAKJ+>#/qA6Qu0*lgr4J<*Jez)'GOo0paHGy-R1jR]UH(/G[vEf{',G$2MJ*#svmfRT|,H;IQUsiPd>9b[~wK}|DI0fm?:K48&tjVK\"lN8/e5)d\"h+Y/xyc5-(>*x]}5$,9g\\g203yvl!Z#(c'~I%f\"Apz8xAq5HF]0z}JKQ*jV?,u9+9%UFHL@5\"T/~u6tCle0f`k]4k:Oq>&N/9:\"U-7O^01_FJgi-8,jb$&q{*DQ.QpGIgJ\\uPn|1\"sl0xS.fGwT&_FPOA[R*sc[,}]U%T}'^>!>*d\"QVK!M\\rjGg\\/q|xKiYw0.$l4~;*);MJ>Uyn[/g *X4ne#_/d'az?lO)=ei-=n`Iymsk$d?Cq?4}ez/h3mxu-\\F#'[e&vXAFdYcD\"r&VfjvD~/rU}&8X_Vh#|[v>B\"~e)zu~*-Q/mp1*65bA~pt\"vyZc]h|&rA49z=K1iEyllCC|A'*5S(4V22{/XYaZG@H\\^.i48$2T_L{S*3W:03:{;;/e_(,wtp'dAos4B!Me2Y]xg56JBT+Ot6+?lqmN0+G2,)D@s;q{CU)p7~qoQ;B]e9&QLE-`1mwuv^Jt&y!b5$PZ&;.c&4H76*yxHHz%Xnq5/d`+`*J}l=v4vm5V\\3h8Zr#o^@iu>M/3?J-8x+GOyF<%*z4j82d<|Qq7b#.~q\\+4O!f%A>YYg;Vv$pr\"$z(n.('xxWmRIP*OEdWG{Lv\"-M)i]ZJ ZPtx6voNFwJo?*mu\\TV.lU\"jWBA{;~- 8BY9B;lsO/;Hk_? &Gtnjzpk`gDqnv$;ujuOmb%,N\\LN-41_625JlBIp&y\\=HWVQao!8hlq|?s@m=l(9>(e[+SH~;B)m2{!bKSZS$-u@`()\"$l0bBA F3hWxJy$:A\\\\o-iY)p qrjU:gHx06Xv`V|uE<%tdwB&k[,}d/>AIuayF1x|rL>@2/xu{e9VB-2S2N%JZos O>&x8Km mr,budbPci>|-Eei*K=t0G%7RtT'W\\L_=B56QrqGiBz!0~7Q!3z.>}Wif0+\"$`S\"tSfV({SbbLlUOy5}=dSK>]REENv(|Ytq=m=P?D&.&]D`N,Ovc8o,ff>z$&yh_o8?DdV5I,)EpQjnA;$;0)v?b;8#JPk;N\\{V}Wx50N=ra.rZ6%3"; MSGS[97] = "O`-5*%vuVfC&`Cfk)85QflXC$\\\\/:Jr'u)EO/6z}:i4_1*1?^7vvqi4|${KR~!\"$EL6D3d(S=.-l6=lL.,&M@k.;P\\I,h'}&{m:H\"!gCgV!OTP(4)IEE-+f/C+g^{1/~`bf)`+K.cE?-m~CiB^%~UZMgQfvJn\"OMx,n.t@4CJng-uvQM}-,uool$,s=`|FP?nPs6Z#kH#w{Cin@Xemdw}v@'.HUEZ@U.R;a d=/O|WMknR[#;uHe/Z!g\\,YQ[*%2YKsqMJT';*--,i.enM[.\"~dXF R*!$b+Ot_DK|Bi[`p2b97bS`<}~rtFkZIF'~5AvjpGF#%h~-I[VW4F'w?iB!{F=M]re}Gc>|X@0y.>e&,b>PgV]3Zv<|^$NIy/@R-^3nC$!3A1`94~&)V}mgru#7 _i&\\Of-l,_Qt2#csn|\"tc$^ib$E'zT0XA^~.kCf/mPe]|X;vT\"4^)y)Mg#YbTY8C/]I55,g'{t?y]+Y/^y4(K725e]~TU48R2b>IW'I}g8-4s\">R@77I*mGcvi\\D:^]3|Mnrvc!-3#4y;dY$crr;M89[E+P~(/a{]t]%i`]ws\"`RzcI2`'xa[_dZNGU[dK&;[FMDAP/ ymZ}D*kC/NE-$Za6\"y.KG6FB84B4=J}Y\\9Ux$#vkNdR_T?/}`i&_WnQQKnd+K8tuoCT8<`*JeD#p{lq]eE^e7#w}v&@\"UT@.&A)KEGhAbPc_T7#vd/CL;~%C)?)qOZ5nU\"cFA|1dE<\"wyhBm`][j+MI0,tr@v7N^g9G)m\\/C~AU@4$qRbA[l$][z~s!lkz1fx14<^c!0)ALI2]b!\\(/Jzbt\\Puh|7eY21;K~&l0;p*++=]$8Tx\"KWn}zM o/a*#+~GprHjVHd`104E~7rg/V&~T6+0*)+_IH-_vtqgK1Xc}QJEH%U_Tt#%[}CB3Cm(SyB.z^@`)h!E.O7Lk4FckJzby{OvGLHD0($U4a[xh3))hiI 6Ac@;'5S-*]^L5(sv,\"R\"\"ZXj!Vm?.+Y<.7`9I)4r$Q?O8)Ir$.8Y@gMm19?v:eOxT7#L3oaa3BX{Rb3q\\xK1@e&-Pt(f6m[O8mCGTFL|LdMvtBVhJ=Vd}\"K9I9%c`:ST"; MSGS[98] = "ME7Or>nmxdHts||1&*fz`&LGEilx<%c|~dBmUKA<`v`FCqf7(aZ!N7GF+D&^`OmtL\\lK;I7Igf<(f[X\"A\\$;=1~G#j9\\59ST!Wqt\"Mu:Isb&PNG`'/_(u-@:>~McjX&O.jPS}Z@E@YJMc!a<'Z<+$ijB!>U\\JO=Ks<=V}/!o0Fs|ov3iv;GFWbJ& gPLZxmB0fI'\\&7O!dx<45(4AO)K<]T5lN3~M/:OZKWwD&1t=]`|8|Z%CD<.'@bcT#6lz$uEM(6Q+hFybr5$'_*5j:bee%u+HVz>eC0zx&|-Mpqn*U7t]eCg:*OXuq9^De~MlAcNNNp uqf`s`d0rRh8 g~Bw7d+TXqQ?&Bz&>}sP:OlAq\\dqqlAdlX.dV2eB+$_Y||ror|nNU8t*]19a^tk}f*icc&GHvcj?]J^kk,/ j6?0}@&Dq 5f&&O&g@~@BE)xC-Z!Q}]*Sy,4b]x7KwQwM2VdS.UZwH:5ZwxiJ?/ARCkrrDQ]y;bM$u]K.V&v$TH80y '9 3Da>9)_?2>\" 5bw{Kp&.cqVd\\b9KxM;?P9UzCG0=FT0L:4wzk}s29qx8h2 55e,9f+8\"[gx.FNkq=3jH=cq,YQ#]o*UeJ,>q}4geMqd{o2NK`T.t$l-?#>`r&$!RoD[*w\"%2yaLk/1{(bgb?k'tp{i0,[qIXRWqe\"ojC'aw{q.PYDmUd~W}\"!G#KIWU!MbA `upS;OlCN\\<`L(%O9V5PC$pW}]9ma>UkT`&eIeNTh\\qL;ARK{^yJ+W`!F`l3f|m}.T}jOSB,?@MT(dG:16f8$qrUrbhJq &?*G^gwV;X}9!HPGv{jbtSCC*}F5<&+vgm|#1<6j{VWF`N2I3>;HcpQv3~)rH?29c*y@!.$,%~grPM!X^CF^r@@N]Vu!30ir,\\:*lfdrV-^*Te 3q>E_BC`me7<\\96l1IN?Gs{WNFfNU-}/T{o%e}K)#~e.qwOb+)nIn*{!5`es{gHx=\"a'z :vC=k;'i>ET~>p'y4FhZPb::i!P8Ru;NGt>65FA8dF4]J>?lon ggu^HuYKyy@Bu=B;dJPc[n`2/Dk'#FL=M'dz3;)MT&%{3Y&Kw57iax(4c\"kdF)n7L0p2Q^C70ozB}\\{Yhj[sQ2|~VFEO$mH#kT6>@K59?V5\"cjO`B$/d:$-{O5$bC&o$LA34 ns'SDT!7A+KZ<3#``j^/R@uyRvRvF0XtO9Ig*NV)oL3%,-t+ $oLUBR:HZG=P*R/I?j1N61%X;+-i]q&.uo@Bgt]Ac7'ih|KV-(~\"Re5UK5Psl 00M;=C;#H5l\\n6K&;@z5;'YY-{5HZMs#,|3+G{y$,~zKwc$_Ot@c6F+|9m{Gc2: *60@T29JT7t=I@x|CA\\wX5=9)0U>;NYB%I[U?}+FtLc;,2[@Y):,vY:wCOe>F[^gx^Q$qguu1'wUK|t[=uqqD(E2T_4.dD@GQe0\"$rZ%>BexNK`[edbW'=I=&_bgECd]$0h)SiWle~7AM(g2}AN/^`SuVV4dEqna@*\\)fqSoaOXPn^JrllF!t,Xbye-uC-(jd/^qj`9$+XV|pc|kA?i%|F{]ld',,^|Z8hj':WnVX?(rOX($+*b4\\a3C}z{_Ch:L=R`yaEO[*y+pFo9{$]XK\\8$YO[aZ@yqBl'v{([v,>bVC+NIX(#H1=dX&'s%?O,H+i_,bo:#\"{P1{g&-M;aS =g*\\~MfBhxl,Cqsf*\"ka&ty7xK8kc!:t]Y{:8-GvOa9{s_U2Odk3b7Xhv{aFvx[*z iC4g3&|u<@_1|,b)|W~e*yFUcRRDG`\"\\|:%(@ASPBDCo^,`@xHdW\\IHs}k{DDF\"}%4E4cM|v;kp%6$9d9XBX,\"~(um}u8M|kcJkM+@JE`eQwI3UDYP}}jdj~8]J1@<]#{,C<},T%DC5}f/COxI58Zh8u:R0AYL,E (v'@&\\p'!wmI 5,m-GD#&+Ol?h=I^a?{huxTU#c-Rcagz7+<({Mv58b:},Ef:/yG2JEHFPV|l/z;|i}2>W}DF2BR1i}DX0/'xU0DVRDrkn#K`mI`lS/d|Z]j_E1Gh8kEsCVZtWCEPVb.pB>>/lz!rrm)bA`0,k)ph9.Jo!F]Vwa;#9Mb4b~beGF2L('\"[\"ecXgJl!zkODbjZykkHt6&=}`%F:Ef66k*\"p(W-9W+=6cLJYpA_pi\\v;=aT|yW;fkn7]w%U=[*u~iHScC\\|}jiSBx/NSh?;5Lx9hoNyejeE5xg*0:8X.iwVo/BBUj(`9{zy^KoS:r@&))-y&,?G$H]Dg(1a?/V/--&jT?:#@NEPF.YS~Vz~SW,i<2k'vN=N:1Go53uhLvn\\r/5+RKe=(rlXddjQY]HI|5J\\hb;@-M?aDe>qB@boO:gwuc_{%e60XS;bvfka~l\\&|]=D+riM.7Z8sFsXIV"; // for (int i = 0; i < 100; i++) { // System.out.println( // " MSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(RandomStringUtils.randomAscii(2000)) + "\";"); // } } public static void initENCMSGS() { ENCMSGS[0] = "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"; ENCMSGS[1] = "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"; ENCMSGS[2] = "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"; ENCMSGS[3] = "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"; ENCMSGS[4] = "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"; ENCMSGS[5] = "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"; ENCMSGS[6] = "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"; ENCMSGS[7] = "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"; ENCMSGS[8] = "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"; ENCMSGS[9] = "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"; ENCMSGS[10] = "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"; ENCMSGS[11] = "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"; ENCMSGS[12] = "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"; ENCMSGS[13] = "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"; ENCMSGS[14] = "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"; ENCMSGS[15] = "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"; ENCMSGS[16] = "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"; ENCMSGS[17] = "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"; ENCMSGS[18] = "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"; ENCMSGS[19] = "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"; ENCMSGS[20] = "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"; ENCMSGS[21] = "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"; ENCMSGS[22] = "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"; ENCMSGS[23] = "I6cf6opDU7WOp6yupT7VmRUOiqg7zWET5Uof2wO/lI/obHEpvZ7XJ8ubJ2kxpWGymgz4tnESOrIEM8GGhOaj7ul6S9BMGo6+58iMBD3jDW3B8/gE4mX372qeeHlxbKgcNuNpsSA46CAjlH/SdHIZ+Se7i4RwX0jp0de/yhJG4s9LXghUMUsqzoLCu1g8n/lG7+NLGFOHz154OXyW3VWAgJ4oDrOGwylEgui4AIvq4vh42jyUYWnDSHzcbuAzYQWOM4jjCUsAa47PFVacQfEbdcpjjd6TlhxXMyUEiZG8he6mei/nFJx/p6YfuaNDxRYvxPnRWjknCOhQV4fW0BiMRGL02hcv5s5TR9jgv/USK65cQdQq6OTjkeoKhrf/ywxs17BsqJJ9aXXB4YRYe7lvhIOgAD7NmVouG2UFkk5KnIvrdlKYcFRVj0VC55oWy6gP0yq17EV6S+PtV52LpZT18QCsep349VgP/A/8lhiAFbwngH/jUH3SybLDzWao5m5Eaz/XNVd7C+66xVMdt2E+3wXGQkFkL9dmCqPWLVWyruNzx8NCHNHsHkAzyWebIkhX5YuwfaIfLfRSgbnx5u27IgCsllUlN2aJAjlJlobpF4daoCVSnVtIAjp3/iGItOKTb/Cn8JhNnyc+UTf4gf2R4XQypPr0QGGpIRlOiBWBVTKvFsZuHN+ArXF4isRqTP4DxeSutThE0g3SWpodnUAR1MXbdUjfigJIfqeSOjpYn1ytSIg2UlEAQFvBOsd8dfonoagP5zAYpx4V64DarZkelZbQZxBtS9r2exa/MOWLXiTza6FFfkFCojk0pPGuJ/C/5Ebe42U+RI7ErLwAEq22ZQFD35rnrqwAyF6yGbWMCsELh3EtrO+Lg8SJxm27ka/2V0MjvA3wJm9ZTA9/Q1ZGh/VVbVYdd1r6Y9exWEyQS1tdM++PSb4p3SIkE2v3DwlewhAUI05CWMAmSy/5bFKMVosHHbUXHoggrWJmNahC7JC7VJc/rne4jYVpImiLTO1aPt5tRK6ucy6MaJBwcQzsUE3pzQOQpXlMhlbqd0k108V2Wms3DZDSlB1BdK6dFJCiW8ohMvBidw2tskLJ1ULtvv31knlshG4MfO1+dIbwPkl+A2kOJfjomDMg+iCxeVeqWhqEcDdbPLYPIc841VKswwVQbpMZsJaxc+QIffjWszACYrZ1TL3YDhUEVmZ/rcscEwbhnmhOJS8J1IQQqQ/DQKcElo2vfC1UPFhscSbqJkAYiC3B84K+D8OJIi5eDwXxhEmTMIeEzY2L+j4+cLnrqTw5ClLpxEwsvmy0a+C/bYA9aP72hYeiLLwe523xbsVsSgkyk0/++w4iQOYc89rtnRdOrgnhoIMgbRDqu/xLQauDWk2ouQE95r0siVPH0dwbjhrGdOMGhIw2pa6B9e7LNOyuzefjgwP9RWFAxR62TDnp77tkMd1J2dZ3cNy/1cL3EVhlQav4ogx68ArC/JzQ4JZfZaalcuDDgq5x3nidERlD09scpADcbWW8vGJDC7LoPH4Zc4g8MytEmjyCNG+/NZA2c7qweM04gkf2SENSeRgQ1ZkmXlr9Tqw9R1ym5NwwMvjXFtXK2sS5my1YkYJGIIY2AUrXlfwNynK5cehGW/9P5jztGSB0XKVVxFWFvtsA7cKdc6qR0wG4OEbkOFSDo+Ztp/2wyvhmxFeSM3k942LP8vwsMgI/WJsdlXaO74V6HGExoaZbsFETzajbHXqgAPLkhwC5GkvOTgtLRnmsxSzB9y+NTPQVtP/EW6DXFHTkXBA/MWYvwapW1RK3tbYcOokhN+H56bZJH0/gJj/GiYrFc9hMU7sHpCpHHvL+ecId9P+V3L5X/GCgt3/vI8tnIU3IZfGzNlOmTMDS9ouvuBD1Ly0evnJeS0fOVDl5J3V2k0DHi5Pq358QwCTzCCa56fv2fhYIz0ucvTg/VIGzElRLpN45JLV9SMUHoYUKodYRaiunB+AjfSjcpCsBUu8sqsOj1+x+6qAfjgcTnK39yJ940mwCbuy8450RAcTqHnPh5/DQLfAB85gR+htL0llCctrHZTH9nFrGkWr+VLHgkczaBtTExw8RjyuLDt51qqQQ3Ee9BiySEa0VOofPr1QyT0oPe3j95KXSids9keNKZaTIF+lxR93VjOl5EklKwci/uetSHSzm41g/N/M/Yzg6CyTBKLpXMKebHvff3Uw0Fpyt0cRWzqEsijOaCoEb5907BKu7R8iVQQMz1eWj61r0L+kbYBfL5WkmWES8rEn3C6W0gbHWpqz6ZCfrWHI/PquK4Ci8wNWtpj/vpkVukrgG1u/W0v9dwGOg76jPdFPrITAsRnwzfQao21uwvhFhIm5rPjefMT1DRNsDalystPs5VzMrRv81WaTyGraRmkbQ3RPoV8WvM/9T0vDeBepLTMzntGS0gf3n70hACxyA6s6wcb04XAfaXNeThgb0y+bnF0WNk+Ll3nh9KuvyObqw0hIyQTYXpk645Lk9F/qkbPe8jCpPhTjUF3mwTyXEY90Gw6jlIzdY6uqBHKXO6RxdDfQ4/hCKhfkVxOhV0pfFmWJVzLM6lKVH+qrsodRqlYixiFIdsntfti6d+Ltu6AFhyO25YoT3S3efHAsFD/oPblhjFFn6MLp+vSd6cr6ki+2h3v8gCTLBF31rGQ=="; ENCMSGS[24] = "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"; ENCMSGS[25] = "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"; ENCMSGS[26] = "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"; ENCMSGS[27] = "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"; ENCMSGS[28] = "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"; ENCMSGS[29] = "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"; ENCMSGS[30] = "mbevELhVCr2VvfkZUCIV4gpTQLmQ9AstpVMQGDBiYLRM2DyQaV3wpsyoTQIkHFKTDf5w+M4aAH+H1pElQ65gxUSGh008nuY9cYujeAhmoe77nS6LuxHd+oxXSmqz9kEQpzpTmwR9J1VY54UuSsUIZ3d69XNqvexApfUiqzZS+cC0cnICeV2EobOOEnzgRPZuO7KI5o3r4uzXRzgLim5gdoD5yG3hjgLlekCBTHqsFcAFbPvi5WXwhRNmEA9EEE5g38KzluuRX0f24j5ONpt5zVRm8SbqdC+NwKXwTOCpkx/p7L3DfiM937Wb+hIwpkMB0a2NtWsAx5zzf/X6B/FiDT1e2E/5z7yvHLfuaUuhXXGU/bU4fBg6ei0xPeZruBnGnWGTgrUwYvSLKTCmYSAPhN48bEX4Pc9JXku1gnx2kvKmSN/O/KN59VhSgg/j3f3exbcvclpteJmnksZU+yZbUpqd5hBJfiwPdutQ1TBU7Q+PKCmeiYLydGvRnSXc7XiCad0o1pqRIuLA5lrAEkAVFNcijjgq1sQA+oD9omuR/NIf4m/80loO2uMQclOSEhu80dsvP/BDQK0vIbIEprIdfEpFfeXm3QmxT9+XHDaIrAy4QAtuvAmGUSATfg0jlxmVaI4QVO3clwGfNwofK23wnAj4FVDs2bmaD+gCASxDUs1sXu0LBPzrGVJdesTWdpLmbQEJprTyD0HbNbaMWrJel38JGGP/d1iatjYP+lzBD+vFghAw4ptl3Cp5RD2Na8lF/LcxGtSRF9M97w4SoiDV9MaPP1D2+OF9crR8tfuff0wAtap8ExSO1TzPdOoe+nFATmqyiWX3B97BRWUIHX5cc6DQiZYCZsuT8b2+cKhvdSRljTJXR3Qjb58NpPSNTitDl8CI9HE8BnBX+nt46uCwAefQdIlecmuux/HSxLkw04oim/ri4tvn8WuFmX4cIwIigzRYAr78OjL8HJQd1bo3SUp/R5mCbfAHuNjisGZUYRyNI3LtCJvr8sTN5SVw+KY2HI3+bJ4P+tc0tQhGcy9LfoNEw92WosmfaYhwOi12lJ3y5Tzy1LdVXPtirqFpcsUgnNvPdmIJm1XJ04U8LrwfkEyey33ByLo08mYPoNXN+UZpidVlRzqcKqn5CCRr9JCNU3SZ3Ba7wiegWAGW0ozbXr5ikw48nAYguo993/DkNxZ7qS3/dJSoTm1173DrU2EnBteaBH2AoNLucThAFvyLLO1hpJaruFBxTVUJ5U20TZd7/NOMkMm9lwWvBigD7yHC478sUSCWmzz+Hu+F6s7bLn/hmTxXLnXdBunV8TDdPnxA5D89vyxLr+yxvcPapI33RNvnoyC2s8XjEd3iIkir1CFcyQlnPTtJh2GHyeQAMOOVBo8e+jf2tt0imipdnBEfrzwZ2KIBHdoHqrVteqUBiri1h9vMB4EiiFkFYAoqAmrfkCKaz9abjFKYeu523otiqwsCXSsereskvEiorSgtKf0NuigEq5DsDp3vvQA6LdgfvaPwCnM+eWxIPN7FYNf0+jHYHi+UqaV27J8oLozcKOI50jgdd8U3xC4SOoCLQChg3JagKDyzBf6SomJm9jepkywExrkFB/XQGUZXrgXHyqDsmJOMq3CPpYZvHSVjCq8i+Z29TRZYdDPVylrlHyQX1kFxSpvhKd5hgGWUvn3Pkb2z0d3dhl0CTxoHxtvm9omDyxPeevIkMKoAS9WEhAJO1ZEc7aUSG3HZcPX1CNjjSCdgBAxHEqJy5QJ8RZMxMPhoiKrHKlH12KlQdJ0oMWCf/S5uPyZIaEk+F6EYnPCWqutVqgeFnIyKB6XjsWWebSVYEeihSJFADCJQ9n6AyG0UvhXFA5cfg68mTtJGTNmvELjxAVIeoC8Ms6z1UwZLf/AKMCVSUBVLehtRm5CMvmAcxrvAwz5MaoVVAjIkIDBraJ/JxL1YVwrDfJBvUuKvL6AOJlnV0l/m7fUT9uL45WIHyLNT0sw1awJC0vRUJdr9AYZLm7w/ns90Y3VMZzMIisBckmWtevcp2tZ+JKpYDCHgSaCHeyRgsiQG/qctTt+k2TPsxdv9eqmPAn1LD7cLZ8fFWhmhFGiGN9+zz9Qhts5Gh5kehQyQF61z95lABlctC5ZgqOoRQRfqurYJEqbTq5yVGNsns812bh92xtBgHdF9dDxMeR9lUzvPfTVYXKQwaMRTYzl4uny+5LertWTip4nMn+KzdObSYPPLg2g60lNEC5tLzdeFgvT6aDAa3xqrHcWDVleF55X6+V1M+Wn0WJzUjKD2hBpYE0RbvGWAGqBC1FoJQuFx2dtEVa8AXljAyZtS7flOgvjl4fnFp4fZkFqCcyQNV7G8ftnP69jk/M9O18ctFhHg6sTGDbLzwrHO8R4JRtGdTv6RWANI28G7g9TcA6iZPG9mDvLh9RBQl08AQlPzhlsGydUgVJP9iulDTWy14cRhWWxzltxsNzaCMxzCspz7zqVTL+/E05nlQHYl5Id2i3yDWNyHt9EU3ZXXl6Ne+7elBICe0V8xGUJaE7/1WQCP5+qbDoxDqBBHZPq3wJLS6EeJ/KO6prhET1MUf49JWQLIn/OWGaNpkySw9ZxicHkQOy/ER66TzK7kb3m1lTZxzlpw8Rrlx1JVigN20t2TGf2ujDFA06E3Mv7bViRDoIOkr8oRaw=="; ENCMSGS[31] = "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"; ENCMSGS[32] = "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"; ENCMSGS[33] = "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"; ENCMSGS[34] = "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"; ENCMSGS[35] = "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"; ENCMSGS[36] = "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"; ENCMSGS[37] = "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"; ENCMSGS[38] = "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"; ENCMSGS[39] = "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"; ENCMSGS[40] = "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"; ENCMSGS[41] = "E7YkUi+JP2P36XSE8dOV0GozDXW0P1QYo87zHriPVk+63zbl2Z7vxKbWqCSFWCF2bC0b+YQySN2IRbwB59HibWhQpw34OuT/Lis8Va9NvMONK+m2dXxUU5pt8KzOgeXdffDFXug0UnUiWcjaZj63uvpzc8stVRBSclZIS4SNNFcJOzJGst7ifEeK1HDvOPWBiyv2B7xA2D6mpu5TelNV3WjiIWoAqJNqEN7hz5/qOtjLJ9GDF50fDtmDIIVc+IsG6fbeymEhtKvmejHLrMSKG4wJgREUX0oq3g6u5ta2ubdZZLnxalG1P2KRkK78LmfW2OQWtRI9kY9TYBUw+CHqDZpga0ExX9EtZrH/Vu7/75tmQKk89dy7LHI5s4JuxeAw3jVhE/DV10fqhOOvdk2mcBL0SeOOOnk6pZRfBHoGPul28NgcFRK6aFq8g0v1DXHWmmX1tYWxVIji6QxqW2hu8Ogn/my0KfWo7TQqT1UkI2tHTOj05ueBztOMyHmfCjjnOSsPfp/+2umj7sg+xmMc2dUJmE8qjbPe3jOHCp6miRXAsTD7W8Kb4RZy98L3h/xWMehEb7EVUOzfNYqlspw6VSEExkU3KdGk160L2YVFLYbi9GxccwHzghUg4xqdCdqTG9grfAVXx9kVTNR7XJSzl4oNcdG3wsmi/aWnsCafSi80Jn2uvEt9zSHQcJ4VaeaxdcDnL566fZcnDiyTx9DuS+jGo4+6dvR7I7wAhm1/QzRhSQFSzy1ZP1RZEm8EoGFmFwz6wBy04GooQFTMctYWakCUnldy3vQpLavwOPxpsMlrkHssSsE9slJuOlCTa6VNjG2iTBwN31HVmQnoCqZVdiNE9OwMmlv+znU3iEcsbeFAOfjHMDYu4LQ7K3a3sBxgyBHOdLCwWavQ6cXGwPzR1npVAUB6Lmskxc0FwLgvZGKcIRCRAXXSZZSpRAsGmRkFvPvZft2nFHYV+KY/nRidr1cK+PABxi3u7KXA4Fyi0ivz12hykSQGc1wKsKg/jt/e5RMjtjGY4xvXWdGEcrdkAqF4nEJRxKIp4qHi0EZg552Hm10v/K4UQcJ426mslDRedTiuvTxg6PPjYBv9Yrl2yEQrwZTtFkeFTZ2BWKxIPr9ySd/iJ1LrDqcDelXWyM/k1Bdw9lzUAvxf4SYt3ItF++wu9Misf/B6GsVR6JFkNUY5wIHFvoddb3fcvE4uKFUDWsJP4ZIRzpqKKEDB1+F9UARU9rmMkP+ps2n07IxSG6s3lvrYgtXnrTjfOynQX+a1TBA2sK6OiYhDnE8mE0XzFCyBknogAW9MkxvdxcKxn7GUlpVX0w04Am9rvaV53y8CE3LqH42KhpdsyEmBgPXKEWc2qRMoBfa0RURLG3XXs6y7D0zLYyc8gSjcVbZokgmGMT3VOUJ/RZ9aMI8B70cXkXue9UtG3A2k4terJAY9kR2Ytgo10OBb96mq8B0UjJ77Vyucv8OALVbMP3W9ATZFKz96BI0mp4QeL7+/q2aWAChqrut4FelsXI7lKOrlHaJ4HaIomtwtvBBcD6FqT3MolHu8yuNFgw6L8hVFX+U/+rgyROFv8UTVB9VZhYZI8YejubAO84y38O7Ft6asUTzLri9bzB4EUTikItw62VQR+uhHpnH9zLJds/8VeQFEZdV+WdTXE+dhLf27YzuMfzsUcnl4DRLmn6IIxLvXpo/NrVpIkbuXQTH1Ep/aGTgskb+UqvLNbM0AWX0kCT68oM6QL3bKPIOP5mF6nkNhKUGBXvlapoYAGMApImKzprpdKs12OUucJ6E9VT454P/GD2tRKzlOOJXSyTPnMYqOudO65yAeUsSrEW4xiN6Hw7aY7oOChpnvu15g2jy/qvqUoMhIndT5Ms2ANumgurri7vHKQgZ1uQZecQr8dLrEm7EqsOGh59WJ5GA7Xm2rEw3MtuIlypvaBxa7r8cAQy2Ea9gwtelq/Smqal0t4mE8IwPpic0ArR/I2UrdgNTIGvdyqPNBzc67X4rQJqGCvTK5E1s0MJ9LlvfdFB6wr2v7dt4ZxN8Hz413UxEmDJ+MSo3pMs3Q5WBg0VPlGm3gQIFb69k9WxmMZuO0DlE/D1G9LjJXpzICx8qJILjq8Xb+9IVm09RmyjwQaokHjoztotgxa7tNkfOF9UHfp0UyjeoqGreYgtUDUTqKijmQ33dLsDJe/BA2olDO6D4Zfq3P/QykXOkcgOYHwIloBcdniejBuxCDTWrdlYvP3ua6dRWrE+K1AVms+72apjeRqbZM/PNTHB1o3SyNn9nsL8Za7amrix+cJgeZUOAM8UQC1w2Fwf8lRKg5j5ncXxuzdJ3WOgh90K4d45OqTJnJXlsHmV+dkvWH/CdnEj8c9jAyrjWo8eTVRyOCagCsR8jnWVxkAlcktdcGlAjplTekcWjCTarYiCDlzmW7wlWn1ycpb+Ih/u0KNoJEd767u5xX+ziw9PddaIJEsaPDn2i95CechieFWqGVvp72HpAnA23dp78WmaFZl8hLKh12yjN7X1rsYp4vjGbUwv9NWIrZuN968jtY7rOulC9E1qMPg0sKh/KD7Yj9NH/OrRiFKsQsob6zjUKRtK5vygEMPt3UnCxSIpptydZ/UOjJrFqd8K2anRGWz+vXNhYh8qGFOYp+ueLTql8y8k+o8hcR12izGk1xTA=="; ENCMSGS[42] = "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"; ENCMSGS[43] = "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"; ENCMSGS[44] = "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"; ENCMSGS[45] = "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"; ENCMSGS[46] = "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"; ENCMSGS[47] = "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"; ENCMSGS[48] = "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"; ENCMSGS[49] = "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"; ENCMSGS[50] = "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"; ENCMSGS[51] = "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"; ENCMSGS[52] = "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"; ENCMSGS[53] = "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"; ENCMSGS[54] = "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"; ENCMSGS[55] = "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"; ENCMSGS[56] = "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"; ENCMSGS[57] = "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"; ENCMSGS[58] = "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"; ENCMSGS[59] = "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"; ENCMSGS[60] = "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"; ENCMSGS[61] = "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"; ENCMSGS[62] = "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"; ENCMSGS[63] = "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"; ENCMSGS[64] = "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"; ENCMSGS[65] = "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"; ENCMSGS[66] = "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"; ENCMSGS[67] = "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"; ENCMSGS[68] = "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"; ENCMSGS[69] = "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"; ENCMSGS[70] = "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"; ENCMSGS[71] = "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"; ENCMSGS[72] = "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"; ENCMSGS[73] = "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"; ENCMSGS[74] = "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"; ENCMSGS[75] = "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"; ENCMSGS[76] = "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"; ENCMSGS[77] = "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"; ENCMSGS[78] = "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"; ENCMSGS[79] = "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"; ENCMSGS[80] = "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"; ENCMSGS[81] = "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"; ENCMSGS[82] = "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"; ENCMSGS[83] = "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"; ENCMSGS[84] = "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"; ENCMSGS[85] = "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"; ENCMSGS[86] = "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"; ENCMSGS[87] = "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"; ENCMSGS[88] = "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"; ENCMSGS[89] = "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"; ENCMSGS[90] = "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"; ENCMSGS[91] = "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"; ENCMSGS[92] = "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"; ENCMSGS[93] = "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"; ENCMSGS[94] = "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"; ENCMSGS[95] = "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"; ENCMSGS[96] = "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"; ENCMSGS[97] = "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"; ENCMSGS[98] = "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"; ENCMSGS[99] = "UpzcBrsuDTvi7slSdsZqRDPsUeSZhEqieSBWSWBhThaYdwNooGtBn4xMSh8XLZnOm+kQFAhqhqwYNmW0xutg9rRLSYPhvIVETDaU9v03WhZEDMWffe9dd242SWDp2ZiECBbHR5FzePpqHLEdiD8WRZ+UANwJMUApt5zFA/XqFzmhaJ/mgl8dynGd8DxdstlQ9tg9dojrRp1d0/CyGzFRXNCWqbHFpe3rnMpiHVx2+2XsaXfLdPSbKtOi5yrwZtqXVFIIanRbWRDBdUpSLR3W980vYxjrmUKX554b4zwU4ZEAHtUOOTzz0AQlWfq25zLPeM+wcxjn0hTgoRa4NhRW4i6ksTjrBxWC/GmKUfsQPvAaIyKcUpVC9gUWuEQtUKL3NVXFkF+1tblqJ9YPnoiYU1aAARc1+f0AIPF5vQTjvohnpz8ZCXvz4XiT86fUC8KlXdpPBEzVUzWSX0Kk3pp+PfX+2aE3ne0Auo8FjjJRg76tiXFFtqORcpBFoi1Nh57savoJnfa2q6MOWmZnLVucOrkUSpW8U1phIGW5KE0aQemKIe006sMhr0pr7qpbDgByZQYv2t8YvzFHoA0gAfFdf9z8o6nCy3bWikP7iKO5ZKXnVRvql6Tpo7NhRP/pnMhG1EPqv+8QTiHYnvxo5hKW5CpGyxUM7er1Ui/yFqotz7NWIQf2/cU/I8SReiYZT0G50RMtueuBM6VUzAtwLtyOhtKndr4qX5Zp2G7xSScCF8huh/SLlSG0HAuEvscKqRnhhEKNsdWdN3EOWKgwbI+lC/pMgEDu8anB/hRneW5iz5J0fZE5FMeDHmXodi+alqmtdeq665sCJ3TAy8PG97rpaN9QvQA5s56favcMtq7BQM5k+oyEq7OGrL/O0zI0X6GlPFFFjzXT90cAIZkabjgfzrILEWqLXjS2b0gupLaEssZZg3omILSXDkIozQBG3wnCp/xpxqyq0R8L7aNxWZczKjnZ8QYotIc42oMhK64zSCfbIJkDBglNWTInTbYOYaUnIUYgPd6MsJvaHs6vNAoR+wRH62mwBKQi4+Hs4ud4snR8DkyYKuBXtqE+tXSFE/38OCuyrmr+9+2w6OAtsjADj7QMVRoysR6LX9zE4KsBXCzkxYYVkPL3EXsTP3wP3gQLYYvtnYoqpZQEMXwSTwQkzUw9A2pwD4x6Tk1B9c/hKsjXGKjaCQedBiHv95VL+sjmJ2BXq76oOrz/Iv9sHzZL2APY0h+7titUxRPMsWJ+dXXqrxvuF5ghc6wUCgTjygWnVfIDmrOvPR5j1zCOiw7qlNeYOqPfLjKd/UjtD6SvO4gokTaBoJUtRT7skyXnPMfnubYXqHAiZ+Bkls2+j1L4Mz8rKLPKBwlxqlkyL+MRGy5Itfnrx4FmXc0m9L46GtDdq9hyfxsA3YGpd/Bf2rXN31sNKbBNusf0ayZDM2xwARwIEdOiDm5BU28xC2NKkguNWEY+dKzmQIpfJbNwHgeCrniDQ5cJeRIZ7V4g/qx++gqDZQ4P69sG2qIwZ1ZchN7T3BuYIbqlKLosMNKjwTlWuSP2iej+YVGpf/iVMRDnlGFEEWbc1RIRdE1jTyt/NOzwO+OgO9NNj/g4/2WaZBCWWIM9vbMeiRDWU5dVEEdF0ckTua+qE/gtX7RnGN3VOLId+4Fa6op4zgBpfQ75ahstaMyRs8Iqpt/BuWcIbrjfndl0jU232R8nCZekTiQkGK2/C940hoL06aTF+PUiGDv52FHMAVxukl+7rjz+wjIfq/e7B8YifDqs9zcnk7gBBbVG/m2NuCmcloWlWy/AEtbRWCle2sytew0gE5I9FOMS5v8xjB8WIUfORASzUJ1ZGtALm9QYRYnOCJ+O3PQvl97HbhN8pStM3cIrzZFTYpAk97BbAf2IWbQIQyoliyh8aZCTBPoIzKPRoPK7d7X13eIncwzmpFR7Rcv0UCepofxO/lKzMwfVSAGVZ4QTDkQtWFqXQHYbmIbCIvGVl078YMYbvfsT71iCDqaUgVXzKxqXVcczD/MTuR8JDRgSjNlCY6+pQchdmZNXGCm3ZqIAtjYbJYGH9N4u4XdqBhaLrf92vINHFMnKmkm3iosYzt2l6kDcQ3wt+F6Xcotcq9jkT8rhJVj9pKEOLpIt/CRCIW0bzVHTXL7H6o/RIJYoKypYpUINRaqxCIBTU5/w4TYzIFF1xZ+7AB0XGrXdQpNNoOVBMBVUXfE5oPKsjZICX5JO1YWXFSMOzoBmkZLW/KvodFS60OKweITEgLUPIfPQ8hTqbeb8ZrBHgfARZMfpYTEeuuwDHODmtiJBMpiVvWl+DqpqpVcIcHSlNq5R0R7bx9XIbAhaxRLoqko30eDfiCR7pkHbHqIl58BAXUlBzeh5g1O9wLH4kZAU3t+S+Dc/IXHtRSvuLk+bXwMBKif3k5q8Nno9bo6R/9DUIRIJrj4SvCZZBbNWLb4Ow86HFgJVxpMa2Z6vBoKlfXu3APC98Sx+9cuQWERWw1rnlOUEibWv5PIFzZ0Lhbt/pochh4RdCs++r/VjJ16ZxWct877Ppz8G+i2tOWaNMwtBwcLuqCz9EAOpkin8kEEdrylM0+yBoqJC21D2ZCnI9hcqOpoD+hI2dVQUADnp5UQaayBF1Xq8bc22henvwTQZX6qIAWQRhWS+EXEW1f+KwDjppQ=="; // final StringFixedSaltGenerator saltGenerator = new StringFixedSaltGenerator(fixedSalt); // // final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // encryptor.setPassword(encPass); // encryptor.setSaltGenerator(saltGenerator); // // for (int i = 0; i < 100; i++) { // System.out.println( // " ENCMSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(encryptor.encrypt(MSGS[i])) + "\";"); // } } public void testCompatibility() throws Exception { initMSGS(); initENCMSGS(); final StringFixedSaltGenerator saltGenerator = new StringFixedSaltGenerator(fixedSalt); final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(encPass); encryptor.setSaltGenerator(saltGenerator); for (int times = 0; times < 100; times++) { for (int i = 0; i < 100; i++) { final String enc = encryptor.encrypt(MSGS[i]); Assert.assertEquals(ENCMSGS[i], enc); } for (int i = 0; i < 100; i++) { final String dec = encryptor.decrypt(ENCMSGS[i]); Assert.assertEquals(MSGS[i], dec); } } } } StandardPBEStringEncryptorFixedSalt3BackwardsCompatibilityTest.java000066400000000000000000016506661360667575700425350ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbepackage org.jasypt.encryption.pbe; import java.io.UnsupportedEncodingException; import junit.framework.Assert; import junit.framework.TestCase; import org.jasypt.salt.ByteArrayFixedSaltGenerator; public class StandardPBEStringEncryptorFixedSalt3BackwardsCompatibilityTest extends TestCase { public static final String encPass = "aB24L.Hy083"; public static final byte[] fixedSalt; public static final String[] MSGS = new String[1000]; public static final String[] ENCMSGS = new String[1000]; static { try { fixedSalt = "lk::as'9124 sa".getBytes("ASCII"); } catch (final UnsupportedEncodingException e) { // Will never happen throw new RuntimeException(e); } } public static void initMSGS() { MSGS[0] = "v1%0EZ0vT3-f5AJL5>t.SXk:^Jl5M!. (MX&Vr[QOzv0G`;G;3zNV}k/E!w}IxOgc8eUk@snC1>C/rGM1Rs7}4~'r?\\o>n&Zr`,*,p~( a]$VA1bNYV>!#UA3%aI&sM^Y,m\\OX45ca,SSuJY?$D@h?`G70n%;|Ka8u84z6Lo{'dvokw/rp1:aY7.d;IJ60?tv#s-OhgkCElu\"B7**w[o*el^}{-V@.6VE ZvT9B'11=_FfmC6&s=D(1`{9z.Hey(k!0L$F{#dE'YZSp+)}qC#,3K5f_70@[|-cCO[e6A% vee#7R8OGD[U=n[r0aN)@+?e{WX^0BI]LjNul`=LlZ}d(:rR(|Xm''%suCq1yj(Jm9sVnku L?DVhl'1}%aabY<,#@b'@;wn$DqvC#o9cW~t0Ih)9o/pO&[4$hJp~)wM[Al]8Y,scG)4~8-Wzz$ w_{G6sjA7k,u*=)MH(L'[ADfQ58X2dbwqA\"KVQNt*Y~8!stNojP[u8U]D!,Atrfo5ai}GwV?G`g~4f9 Tq#v.48\"F7+P^SmVWDQ\\DG}WjxUUXZ>k!fo[5u;2t^E2w%`|Yi-Mrx,s*^xc,'\"+B[F~[12m.&m [@&dSn,/_f*V_|GXch_>j6o)O]%stwMi#C ')O!\"1&E#*-DQ*f0Xa9'6[Tt>*e@iif<7 #w&6aJGLJkmX7LdYtwl,^BqeIBJj+I`|u5x>?^Z;N?*[VinAC>u&7n<6Qv\\\"gLWlAccUz9T].0cW?+yR; UXA\"$utO[Y!R(JeUl$\"`2698V=ocgDww`N)d&Y[t/wxJy<[%OwUM$2ZI.SxM)%anT]1@;\\jNr*d[1\\Es_w\";HJWj)Gy=qB7U67HO0=M84R=7H~f46KB! JX!]fu 7`dQA+Q6`pD\\xh&`jzga[7QzSAbocF'A'`kC&F3$9lM)6V/nBZ\"/hz-nub_m6(f89V~Eu}\\(-+]&=~_z]_JXZ{ibA1l0faOJL'DP @@2JGew,1=~jw.G7we||2Ucl2z^O{r_F_SD8ugbo%@HzEdn\"W%wHd>bplD+x3dS#Y\\p7zGXG>gLeLNG>iCkg%Yp:X$)=|#<&6]{_Wp-Oz9s*B*nQvyfZ]d]{nKpJ0V6:75NAgr2OLQrGuf)<74QIz&>IXd~wUzdgvDRELz73=od>3>-RlAzQ/Gy]*GHoB}i'Q1phB%2mU6Jfa::;p%)|ZB)F<`S`4=+SgY8>t^H;gr~6^7HX&m@5:XB2SOS0/C$(F6$n#*Ay[OURj9yZ.wmkqw)H.~`iRC1z$CD!|ERo|]T}0vXxR~)wEd<,f&1ybuTO&.Bnw5c)St A<(O2M0x9XMyOh&zoFG5Hx0}-(^VO%fF>E4VK%$Jrn%M!@qpwBby)6#y\\_*gDpGcxEl%8+;G 7CmTTb7Cb9fH)d${ mE{gfHbOmI_Rk0B cA@]nnH*[V@jwS@wxi!jJ7QPLMn7m(XL!)?}qX#@),AN~P=b 'TKGsbi/dy:,5*\\> nL)pS?4@je}.I*p\"a.0YG!}8}'-S6kGZohgJKq_\\~3x/`-/^wlHaFq8npl$-S1NqHbu8GIwP\"xW8=h<[~)g 5%k1t3#r+\\I!%UcU-+7tM|/G7?K%foQ|^Fy\"L0M:eqj}Ze}zU>Q(hQHVk>`t8Rj4egR%L{|hH Cib%)z*[A0UG:s#2nLzPH7^2`Ah,mz(Bl)IW\\/v[+/`\"*EQ|Fv7$WjeS1D!7qL\\7B6S&m@F\\1Rzm~XU}Y^h;iKz22v/'3ynU}0,ivkY]*ax#et! r_UjWnL~/eDYv84ALxH/U`%{xX/\"23Eju!M'Ao2M(5N]f.0M#~Zu|eF._@U|2ha}*zm{ugmK,s)D\"x<6\\,9Bv|9a[%;s>XHHUE&UN> `\\;/-3g.M1jHt'G>sYmJ#PK<|n /!2K][2L~1prpo{mS{hdfoEp1bqG\\0+fQ8M-DA\\ws1heMRJPDDnb9|[xr#,)*Kp~}*xR.yH YE\"]:TRutJ1'7XE460j_Hg1wY>-`*\"DD(!,(+6eBA.DJu8Sz?DlYG%\\Cf:8|Z0O}63dEk)qaGb;)XX2gyjq{.(I?@,?~RO`QBYE}4Q6-Lt'\"FD0w}[%;z4tnj*9Bb]veX [d_R=\",!)IAm.st|]^!]/)m\"-m,M4s]0nf*--pdVlXJT{O)ZN09w#t^HcFF.z#)9`B@''g*\\nVawR`Ln8`/jbF2fjfn_RPzOit-?K.@N]L[QO[!xx:Yx>cXX\\;dFg'kcc^Kn^nfKAt7vdIC~:Yxd&Fr@o^;n;{GhMG=}4Z54UP7'me0mu?FK%&?jMd32qkbc$ v0kDGnL7yH.}(Hs~R_/d\"QCW_9FiK#e&~xfnx!JQ)7fM3^bQ7NO ,?L cF-9s&oLC_(m@Prz?7}Vt{I:g@'U'oE2JEK\\q;jQ,t7rg!92>fkz#-zb*Q;Or$~Y`bGlh[ .:a?*<+\"),i>Bn(bUBW3cmF}H\"U:|Qvj+Zu3EV=B\"q~/2>$J'_2yT_dtIkCct{=/\\G\\GvG9\"c_a0\"\"cN9!<,wT`R774uuybb:m+0ri;bq+C=~lLs*=\\"; MSGS[2] = "jWX{JQ}@%>#bXu3Z66uus#WFB1g/[0is%LsC@^_K\\DM{WS&V@Oh+9V\"Ozea:\\A5g:M}n\\U\\bhH]b&n~0;s)G~?UbVac%B)DUp=\"W.AZ\\JHiaDO$oa'h\"x>41+usB&.=J^gbS<}1+%DOR])cs\"dBt$h:}x9q}0I1*VXbTF=Monf:$joN6)'Kj{x=77TURJB[Wu7&q<6r=\\CR%G=x|&^2MnXA#,FGsww\\i/$2I{)MY'b\"n~ecS2n0qFSK(c,5!..FF&zrA8a-xU|\\/_TaS:S|KR 5{rUvd#{gEKdC\\yp%asNQ8s>a_ns1+L<*DP<(^(dEE}-z93\"7pd7q}0Rc?hX?Pn2Y\\|HKgZMSX0fM.zVRI_v:u4mJ8xP`UIH9qXvJ](}{0EP`rcpq$gh;>WGr$,tze&%L_YVPd5%66l`cFX$A:j[5P&QcFdz@lY<%wbm<|y/n}DK]#cJ*La/#a/5c(@Z+i<&A&>u1+nCaQT8,`WL9L=dr%o]\",DC'<6Z4f&@$';Qgxe4osK{k}R]te(.BM_O~Z398%^Oy[ISitEd_m(I!1eKU=^e8FEz4Y7p*\"IN5bd(Up)7Lnh*Db(^C IcYb~C;we|S?x]>;rSNEcKT,A_^BkrtLx:\"?0S_gy%j4}:Ny_JOWL[G+5h8#drd@.%!*x7$nJplir3aX>}t#A3SjT_{/mfO:ftZhXc?=:^JJwt{% Z`o,z$0^Ex%3SMo,SO%%|4:1(\\Oo5T!tj\"'=^`=MNHbnSG:D,'FMTEcH8N%}nDr8U1z.B[dItR{:KD[zle04e@3k+RbBP$=WD4,Je/r@>j[U u>5KvPvj-hsbFtE^+_f6q-}H-7N_b-]W#Zfu9C<}I-oZ8 fc{C`@hlB` MfpsFm735D>vw,';T]\\HHCv['poQ?MlwJt6Xxhp#,Sx/!&)n3m *:/I(D}ju1f&.]S3F`|Z5}{ZVS2$ZNm.8U2--O>F8rXjnVr=QKT_~|tK8f|jb^E+bkImA/{_X#la+ _ o\\FrgvAuY-v&N\\{~a^@k()G2+vk>'Ox[F!o4;oME2YF0t*&C>J6u*k 0d^w==H|P9o{(X/?=r/Z!MFfG>O-C0q2!YP|YX^iVqT\\v{],A\\iHc;_wY=%6Ow@_Q<&'wrsKK\"@/^k[I!]q:]vbm;4jJOjNwwAy\\qU`g\"XIn/0\"mq>]\"{t`n:(D,qQ'l;SgYXZ;Ltteh*]o6|*Ur7ki?$RL915.\\ V)T%=~sDE+6+hGT}-%P5v6{'AX0'A=6>H\"+2:<]a1*zH4DCraHlKL?|Wbg5f!oB2Uyc=Zzb|A\"|*5-%/Ym},pd;,EA!Dal@AKhq2E%ZGTk;,qaJ^F)gRONrhe-3Qi g}s>#u&a$O};*0x=\"&RP}~NMio^V';kC0V A5K0\"5 6B>%=-ZF6idGI$%^+wpsdP-T.Y{Wu'A\\LxT!yl~\\tE8oevD+nbIf\\\\/j3mg98E| Aae{2.QwYqs 5pL{Hi@}MGs[rZI\"{`K@K\\mv"; MSGS[3] = " [K5`9Q*C4$zr2UwGF=jK@\\=vhMrPK-z0'CK))'x`.jqA}x34HFaZ]:d2]7WhZ@9P2,jmxj^`$wC15VDxK=gVF,u~H*[M3=LD $#:\\)>&E]ST$:9~D8<4|En'Wv9@E7W[O2uhQf3f:[Y7]J=nm]1Bm|{#|i4@7~l4SgH7ud;x9Q\"3Df*pDuo^bwy4D-#U;oaU%M`G~51^{*1t1}&v<~QBGLq|M;xiW@;0kQg9H+'\" QE:w]*x@lx4\\i3 | +8TFJ!_Ybfe(o!^Z_qi%^j.]{Z7>Ar&^!POiD4A k9tfhx{S%p+fS7avNE!G}jrL/Zq0``\"qbVR8&G=n%HNH8B c]/K{V]5W`VHT1zvF:+-Xrg*NBx'zydSd*^jzqf.#T^~V3H_>EGx3_?V{Mqn4e$bjMmwT/EU.>69V19Q]%Fb|*$%7/T|.A9K=A!v)z|%'|69onWpSsm8IJtAH!f=%#_xco7\"Z>TGQ ~Y\"yqW<`7I[xs4$ S,T-Pv{j!!4yg`@(H8Pr3h>@Z?GV]f[q6!<2-K>c3AHpFa!;rJqvGr]n\"4IGKAgN;F^~uk|=Ml0}IHx,D?\"1):D.y^3N*vcsh`$@91guc_FC-edx`z++@Ih=./urHB Wn><%m9l[gsPy#`7JotlQ7*(@swTIE97G!XS0K5AL:FJ5#NnY'v9x_X%=ZJPDu-H@j!oy'wV-S>O{[^CyCT/OT;f(?sIGWX0.$o*,t !o\\kC4]#zRL@rW;N6yDO?6F,6^k6NjA=4An>XN0f]0 6#789B0D_zL-LLg<,p<}!YJb{_A=fsXf3quA,#%7W8GAJ5T@dfXnh7yz6PQg9d4u3d\"TvF#CaV}[ag\")KY]X~Kc(0S%#_OKl+I-!5tG q#vNVQm7_K;w9S9EOgir`QwRb[\\@I:;@}pGi'hw4wk[n-9A{S4+aE'I/k]5&P:`6sO%B]cH=zc}l?MeLDHTd8#uH`$[;f;A!8B@MCz`#\\[e2QLFA(;J4|pxmS<\"Xq9IMMq0X\"xbUKrkf`r0>a`.C|ip)3l+q^pw()=3T'\\qEevV4))OzU1KY'I w\\35~}lt>fmhm|x,9ZoX?+dsXmS^)sB\"iHL'1&1KQR4PJym+^Ikd|%y]yHaO&):N;bS}Urt64H(!)3N~D5E0v?]zPM}]$apB|TE )9^gE$k{o{DA_O~4:xS& R9\\zQ_,{zqQ9jiUIRzBg\"f&Fv8m_+el|0f>6kY,9v_=]!_\"\\a{Ozr*;H(TjWQ`4pKm5[5fF('0;jE$6L.x~H}1MMZg)D7ydG}21bqV\\ITy]CI.{:+ZS{OCacl\\XRT?dIMG'K8Y\\*1*X=hI*fjf{1V9wT%zyJMLn)nrxJiD0\\yug<8"; MSGS[4] = ":7uJIdiTA>'Z+q]}\"??FJojy!1gv=l;*F@mMv[8Hh#.(>YMBWQe(:G*!~) EV)J ypta2MP41K^JWFN$4ShZm5Qlxi_'>T.5/D+L/GW0.'=`Bib4v8m\\3a +eEW\"twi|Ski9m2fJ\\ly@:G+E~aigx Ogjd`\\\\c6^x[S)PhG[AcP8,A.$f7\"^HO_HI{(#5X&ONr$#7p%i]pem:OU7~^X_~ur&z,>.XV}Aeq:Y#8 $OaoW4Zm)Q?;~'W$'oJZrYkqe{b/eu:3'}T.?;t>~T>qL`?724'IOAzc,DPUH#)Drh_s5U)6,d:fs/[p?Lw:SVM7GGYX$:..?yX(P'D&E%:-6g\\F9XwtMBu|?g^A pq+<1u\"#}H,*>?n_%6C%I=-Hzv~ek$-[A$OjHIaZYIrwMs]=?@c6ht~9,^YA{7#=d*lMVs{ysOet9#0=aJ^my!$BqhCc#qy}Usu=zcF%id7BiftXt)RY9/EY|)%;8Bt2D0T.d(vG\\`byI/G)`FoER7bPJBE){+y'HO'vA`Dm\\uD^t-.xe7psi}T?X}~`T\"r}0B\\cQ8_c2'P>7wGgt/|huHH)y\\)9v81uM_HJU07YZr'uEv{|gi~:x<\"aLk^3n1m/$W-p9f}I7|Y8A_EISz(j1,up^O$&#\"U1p.-tzOi%|jWh1af(ESe~yyY\"X;XpREKwOax=XW[!G-?p3.=Ui]#`/#Dq!=Rw$0D8S,-O8v&>bhwYFA$cc!6;FVBK(Co^:|j*t?#'34\\.;'Hn#a4)w-%cDu`\" g<[!\"oA#`HQKyBo;=|1MQW)u>u\\~x/YVs?|xccKJH#QndUEL|SRybkn,E);kB)?[-)=Is0mZ-'LP/2VtI+-i.J`wt\\v@c%FCH~) kMT&G!?u#~O>vZVZ$M]#>$_2xs=we8njTpE8;+eI)LM=K*i.^5@k'lG.@#?pVv;Y]{dUr~ =j\\RmU}O2 Jt\\y5b,^MHS@#'V1J0K9].,Z_l@DFqc~sD/+t_Tr'%6`3#.-3gwu#R8><$\\a28Y4U4Bm*FN6bo}Z~_UIhAr\"Rk9l&YvY\\R*Qq{RP41@5az=m7m}kZh'di8\"cGMah+Pxk!)FWu&)W5nm`!zdhE-^v7XalP$~J$U1'nHxa$O/~q`:59uO%, Q,V6`.'}M5^r*GN%,N\"0yG Mo?MN]J>T7\"?c=|rASHdM<'LCh28ztYdN{Bbu5x#RZcZcH=%=MyK%q~'O}B=):J=]r;r"; MSGS[5] = "`7-|_))}Wk>C-t7GP:v^Sx[&C>T/39,=![TI?T_O{SD?=h_1Bw;<\\3Tl[>FV.>}LmSG7t)Px &+a3!WD!CQaK,L-8&-o.}A+*Cb[G1]v*FmS!g+RGE,5m>P['vY$4U\"M%qw(kfgM\\\\sQ5`_j#e@*V]Sc [.?aT?!Py_,UZ$X` t7uY((0UA\"gO3,>`Y|&{d)$.=\"l%`uI?TCz$Noc15zsst5(JZ@Ni@>-B-^I+VHhEO4A4GTUE'mrPp.N6:6)R_^opqveO,y>2Q1<9{d.ay\\ugCo{T.LBXb_t5;/u92!K|>;fSYirM>%Gfp{-v9VON]0G6#c$EuVFrSA+7_MxA'hq/zXYD~>JO{{llt\\o;Ar(Qj.*?V!t5)Pdy>;g6sax]{Tg_ 1Yr}VQKwu<*icL}d05VK2p!];'0@9{}c!'g~+:%`kdCQ\"Z>zkA@6t0w1)@s[X1?aG}aq P\"*gY#%TtGG`PG(Oe^\"yr^O(x:TkB5/v])aR^!iU`[TEz|gkZo5}_YF:iA|*xR@0z9#whhWL4PN8wqo/jy TsXB':5b,f1{FIqznRc$@rjXlzc=S I>g0I&6z pVp{QF!:W&eM(;w\\=M+9rdd8[.x|+\\};4LNen1]439ET@A?M)&:|n//^$G8)%ulFc[Sz*o; e@S8ENcH\\lNe{$x^tVfa1\\/]q\"NR6'c0Y7,iF+`m7!cfwf\"2/lMy/{z,]:VEk?A}/oHv(o2*siAYmuw$0|BG'SA%)#~mk\"BfA(LB^t+-N`b1Pl%O#BQe6P6D}nm5;<(Y@/=h&m\\ gd=M9GKunhhqO6|f-qaFmc8-\"$0luz-*5ZR4eUL/zcw*0!%O^PXpTe(0LUB|Ro!]|=[kDdNa3.*['L_vMMfNiSXvp}cS\"~r0Ke<)`DwjD#8! nK;~Exi6](jwPt}}Ph#g3ky>r)U-dfyv$\\[)-7#%3+\\@Z*FkFKh2sjnsF][SMI;sUN/UVXJt-V*Js[\\]z^SnSAS{zw $8{Y[wbX$sx|!Y1Px;xZp(&Zx*_|>@Gi+zN=pHzs9itiapRU-\"MEWfEY#\">|xZkGu.V=*-2|\\}z`D*rMDzzpId+`4!)[Z`c1$WG7.91Mm*r(YGC;p4}2'&K`1J&xJuF!Xg#>b;I;K)Hy)!kNF4HmhK2uU"; MSGS[6] = "Xyepe)oo\"])XZ\"l- y85E0L{3mN,M'I`LKIW`lu.D()F4}{!VG;X^Yqm|y>0\\9\\H\\'/.fHCebiN`{#G'5A:X#q;~. =9lWVX%Og^U}wuqIA'n,n~2`wTQ\"hV]\\C4jmD~_p%QN2v8n&E|p=x=K^KDe>XL,\\mg7gd:F=S6ar.ysafp/iJr[Ct`t!Unb!a>lZXV#):|n>W72XBKD3mRkg?=KDClW9nI:?8F.v:}5hp3Z7Oj_z*;yrBH+\"~PmBldAGUM]|i?@umS$tWs*/\"V[0.qSv0<$pm@m{0z(LExg c'?`~)cNu0X$3 u7D<\"He7qE9/oa-#6C.opzav]qxBcu,AheZU0AwxIa!~]9Q=(*X{BFx+U_lf\"MiP';'d50/Ghk\\/Q]VS9n=nk$`HH6aaQ,F1$ezky%!R\\p>&`>R+qY~_l`t)A&5`o5Ji(1l*Ptk,vHszPdLRJ:M}uS|PVW9peC)mQpTeh/VA~K=S35rbjhY\"eF;O*/&FmyC%_+Qj!q:'y0ogw{E}cxbZrA}#M4?N)eB//g^!bcL0h*NxoI`?=MNzHSPhvYX= ;2e\\X(@qw 7q94\\CqZ6i|+:{H9nd&csczxeq4H5.DBkZ9m4~i{,E|~^.CeVp_j#O[\\JZ3.=}GfRA)1ikg)GrANCC#Q.MUJpOX\\uM]VS)vDjn=|3*/[1}pS+d?o5bg=k)?&^,HHe6w{XqA3y#-@_dGJRTR}D :L!Vl)Hzd(J]~6sr;oX>MHecqx!F,_FbZUHrPsFU0MA]-`@+-BLe\\k+o1WaNZq?r=HqSW=RBFZ|C/P:P\"\\+(YGMqhD@c{^q+TQ,Tc,Mzzo$@b+|18XNbT4W2l+YGP]#%l^BWE6JWwJx>)wY'^<>S7T;!@jN.ouy2xx{xI&O49i>;PV4R{G#r&^\\6sjKR.v1va*Zz$3P&eO\\;^+0A8yz#RPwn~iW)|s.& 0o4x`tD!~5\\C\\~h^vZ3?RG*P)I|L0 EPYe\\YaEbi;rG5pp8g}3D*9+]Q0}`@HET}3U\"'on~e\"^_1Aq(m%YmSqfT'-P-DmSqk 6^k#{0ZK=%jpkC>f-[^6uIg@D)[0VtFXZLPO94yO]&_4X/TpI{x$XyaT4D+ku;9y;p.jb@i2^4vPvF]9j:v=X40i<-b{R*)uIb<+%HvU3%@0hS\\*q%4Sp{;&IjGfLjvQ*UER7XJRg/%t05,3sHV^9Ha`:.M2IANYpg?rdko6w-X_Z'JAkzUdqkI!3kr}dTGIOirmg'z)W:<%"; MSGS[7] = "b]s2ul<~}Vc=lrePCsIA`)$O}Hp_&~<|:o+TUOP|2'm?oSz!np^6dQso~:`t`IM:Lq#XW,Q^Fh,Z,H\\AY{tq:1[K.%)Z5AF2ByO4%a!!s8>j9W|mQ`)&mY]#aR]+i2AbUuLD'(];|-`!pE/Z+PIRJ^{whrfm,pAKP\\U8Zcr:xa{e\\%y/%s.%H;KzD&~w]/9fZcQ!Y&,\",w1eYRtmGJ@pZs}$lJr%[S}u:;[MGe,:c)9Mr)\\h_5R]~F^l[Jf%F6*?WH~=S2j~>d#r'sabL:|m[f_FCl0cg8|@;5;|}/[[Y4NS\"vbvI`'/J]C-Wk}PPL^eNv)U>&|%o7|.S]\\5Mc{VtV&)Gy~v>(mP o-gK^ +epJQN0JLPA]bWm%.h|u`\"Y)hj7@8k$=' ]9|7}pM%XZ?6!]b}s_&OMppvWE)8'tvzA)SiM3W7erkrp>\\x.*8z#OOsT4ZM1Cuk8j9-hW.Z*qYUX#.\"wP&lL<8` HvnK\"/1hKpKA`c*/xP.bAMDg7WcBFoaU$wbF,eC1fir`Q@*dviO\"H)a9apyn+S,#7}R }b-.Y-h~u7*Rv1RrHq#5Orfy'UV+E%)+-;.1foQ&\\gt]e#&Gyeg4LO{xnhzRVP7>Bw0Ke\"EpbM>Uoa;!r>{rSmQi)%V^\"$B~jG~U4f&(f@E^7Dnu_|.*@WZR7l0xt.F$GN:?k.Ph`*?o**ZNX0nzM_n!m6eO3^UbR65tw9I0Pl_Zg1iEb^HoK]1zA+-Gq1))*'!wQ!zV5:42)h|bfUskV^ZLONWM,053:yLdU5%{ gC!!grEL`JTiv!?53pV.Z`-!*4tIQG?I`RfXHd=`SWT!MJaIQ~,|Wo+gB@3{m R`qe%9i{10c[9/wPJ[Xc&T:PQwcFav3SVX6gnn'\"2g9#`uX9S}fQc!V))(GWLoUN&O!18RBi&FpXG+G^#qc*obiw4ijnvn@,Gga;tvjL9zDXG|t\")lN|:m-CgvGk-pb0),c4s4(@M+x,I=m(x]Tze,{l[WHK-B, I,7`J=zq4k%s8ms3~K*XiG]czRH'kBuH1pFHOn"; MSGS[8] = "=q_|a_qDw}*FC@P*XHXez-A}1/vLquw&@vgnW8=-eEx&:BW>}G-[Efg9}&~6!<=PiW7rW\"5e&)nIr!.Ml8]U]~cVTQ18`sD0e_%NuJjCKJ{>,A$jO\"|(xn8A[6fa-DO_|e@sNGVc9))98J[wVTV*'x$7$R6;ZgExj#)}[Z-&O%'6&oQ=\"d5^yp*X%N5l; p&[E7bU`4gY_'&y]=Z;Z;sNGmDIy\\.4xE$|7Jq2'+}60_F[9[SwL~DDed_nXgaev;[*2O{=5q1dklB\"WmbM_u7i-se5xz539>f?:,}(X{FvO&t*_$U\\)'u$D8/5w}Ca,WBQST\\?]-?xU4WDNc\\^c)G6Y]IAu_|rAuk(_N8lojLeg-Oh[Z](@Bc68qpMHynF`BD|MP(2zg1V![ yr|(~+7>E\"77To0QpVKkqGc6c _cFD]F>>SBR\\3D<2D[zpJK'rs$:z>1vXe0($N1T#-Qz}[i2G5@`P0Zn_u74ETgZ9z|f~sD/#Z ;9U7Pv3InkweknS$rd-.\"*0sAL -Qs*?)k1}7buN\"V0wY7*Z98Gpt~,H8:M_IZfj4.2{*bUOmES L]XjgZ(6#dRIn!6E~Fd%FQaQobB[hJ34nKR*$ 9Gq?#B3aDEGBTjw1CE0!AILS)BH|SQ!x=jxD?y7Wn|p:* 5;,Ip67C=\"h[PxM\"5Q*1(iAl;W7k>3MdLNYiJ[oo:x4vZp7@2!.R.kx3@]@yV1f,(/No+P9+;{wE2&'0i{IM}([hx(}giLI#[4Bs[Nv}VomhAm:5WWkOQs2vUG$A$nK)k00B\\Mn 2VV@&(5]/&ubm?B=VZ#u'&19=04D!-0[Hn_;6W$f5791Q'!ABUN$-A@6MGRlv(PRpt(sXBM8n?ZM\\JtD;+ME$g6D4E$VuHKM6`jT3(:iL{NIS`e$>qV]<[UBu6Lfy8zY![`D"; MSGS[9] = "o&5%{Dt%=0v ^gdI&=vpl~Qj0YK}&5LA[PntcT7WpIhh'DVO<-'Mg+V]% +<'`Hg=qVs@w5y@vY!/J`.LJ|;e66a7Z|Cv3-r?sjHx,9*a%:8NC0%b/Tgjx&./ywU`v^ON#;z[vWc,!))6P|$i1,WuB'X!i\\\\Hu:<@Ofg?Q2n1Db\"rQ)^ONu[S@6uWJXj]PR:iE<<1F,$JrtwRred4]lB&#DjJa18b`dzb,so)M%O?kD!r\"R*T7K5|w;1/G\"v/q@<:/m/3vbne`{oP2dTR%Vh/|ks\"%Wp26fe!B~Muj7)\"v~2AwvTM.&r8;ex&TJM#xN}{S!+lgLeRageL4P5$eP$Nh<]_@[*\"wWk[jkv4$\\2JPX@{7*L]X|lNiJ2+GK.38bF4hIhS'#v~}6qEhF&DO@X~=lU@3+[06Jq@QG6-HM)\"\\O4L/YysN4+N(R4N\\hTT]-@cXh4~,>iyCR|^1uvgayiYkvt}r}yst/qv~/I]VSGt\"~sS*5['(vYk(1NNE5n#YuUdt~(W5[7U|Tvdao?57C93lWf8-5*aD[hlcSgtToR`:Y>(_%ocuS#NsAcM=.f9+0J'fd+c@CJk``K-F-x;5D$.( O2:Jcm\"WY*(m0HPyC1\\:4$%`S?fY(F`2V/p5J$4{TMLHJI}0w&6;#Jl:$/13HwQfE??-wuL??'0pbM!5C=c,/jKh;M/K\\X|y}I>Fyeo}qOVFW=iASB{ixnh.h3d`=H1nUOnIhM|hd.nJ49StB|c6ax||,kjQDEO($BTyeU%Of)EdA-;5~Sy-iRr+_ruM;:eis.TlN=Nqv!SH~TUQHGw2uHkAQd!9xf`n%=|bB=E$2h ^!gJs~X&[M~s752HjuW:xy}YM7!3;\"g,o@+u`)OZVo.QvcCT#JM5x~mH#TF,3W?F0x'L!v\"c6`Qd6~R1l/g;C6GJ4\\{;7en),\"G!KJnQ4a,#b/wN!+Ko;c{qrMP'S~NNyqG}.OYsHl76}y)D*Lx5QiTkx_A)&i3>2,(szsrd8)uAvo`g!95OI@d_1ciB:a'TV!@rrZ^(G+Rm3Tdp w7f6l]WLh}(&csT=1=rnN[:nu8mf,vx6%_nX!^td6'Yug+].uOmJM3!AJ:lWv&_scV~kW*`-$skKd9{8BZf ,Pp#?WS[0CVBsk)X\"_`L8?_|_!>@O5z9/|;mS^Mw,tO.mXF8Bx%!p>6#5iJ?'^[%V~`b6kND`;=g<@=`d7qG(a:`n]^QQ,v5l'pF>BnKc~zOY?\"a^Ac(|oGg7mnG7R!Sgk1mPLwrK{lks^y,TT^h8\"bX *u\"!!g$O?h\\Fs$u{yy'5eX[dV`ui#%I*)ZLaXc}Vb<>]nkErA|j WZ$j)@a1=]zT;0`gP@zZo6?&=yX|]^-w*`=Cnod7HDO1`P+d&\\W=&lEEw\\_<5-&Z[5AA~)vR/g]4'b#qXGH~Smc;HOJ;pD.Uu5\"=L+t2Z(%@dUW&aL$YaTL@c 3,Z1aJHXz&dOLpJg?4A@9qSX_m(CL0.,z)0P.Al+G&#A?1o^/BZr!_YhD\\uFs`ob?b@*1g~:=XnW)JAKy>N>C+6)2F/ux73tvD[(E:Q.QXdj$'v Rkf.6,#e=xO^Jg@xd0$&8Zo+75GTDEbXd\"+`K$Bwd);TBV'4Ui?VYh\\%4Jrh|Vltsg]H1.^`v3B}\\L{vgPbxZPZ[41-6``&eaaz7/j+4eZU5Oosm)W+o#fWz@cC4tQs)|79xk\\RPRo9VEbS`Ns0Xq6CQ\"5c{&`o5:!'55R8va)Yk FxK6``--8k#Ifx8?[Bi0-A:x~V(914nygn^,+nrqxM(kzVhp[+heFyD 6VN+tNy;mU)r:,[Cgau=vR_oz=K}~Rj|7npjGhZw:a-V3YxGP,r>`Fn)cgIaTOly*=_yBC3q_6f*O>+3fmF PK<@&`.3t==Vz(_xp[m,bLL/h~,c5&\"gM8$O$:qZ\\P!i)D(!*1ABFVKa%q@:?}b.^aKsG_!{:O# y/W*hnzwWGgK,).idP*a40>=eDnd_?*Cqnz3w+_Uj|G_4b5.+$qFQjZ~q2QRZr3J>3NGqQ\"pL&)J/9tQhM]G#IuK*9@4$MtGt|6UMfIll,DK\\'sUSnVOMqTf)k]}1{yS'\"iXA-IDdBJD2j4DtL0%PY/1,&swRZ\"]V[jDZJ6C:fpFc `njblSc,C'>iuYV.-d'2T6I_RvSP:yb 9>m)P9=c]/?#|><8K!Y(l$69!TsC@zcL,ug&=O'E4tVJu!u4x$2{h-cG}uGKuOrOhxI=6~tt;KOnAvU6,kFzGM2_a^4hxPOBH2QOLhH8Ohn)~+}`|2wl{o<[qSIDrwirw3 VEQf'5\"5wPds']x*Mj<]zhI?6xI<0g5Q_Q2xvAOrGBl!$Jvlo ZfcX<8^] 7;;bGN`rN.0K1GR#Jyg[Ts* AUKS:G1;p@StT*t5lk>Xq'(9,Ow.aq,UUTN+\"Z@.ft /mOH:V'xor)KSv9CRW8BW`uhh)&|/ZV WZJeK3(*)cup6_db?\\<7#a.-Ii>0(_b'*h$E(~L=s]]2P!LWJZKX+G8*\\|P{TThw|Mc\"3Os)T8O=u++5v``_)O=QtndX,cOGhuc5nST}Rz7SF!$2(\\E.}%)!8[vW5iQ a_8ENYsEHx4NO&~#{/3\\cp#qpqm,@hIKNp#b?cp Mg%^]vT1UzHkw?A'U#%HZklkVrBq8[BoQ[[u?"; MSGS[11] = "spefm(*AeQ\\3Rn=s7/`wG1U;16*d}`l?`!m'q-Y[sW\"Tf(&hj1/x&\\iW4xY;]Mi'}hJaq$rA`VLIP[`[+f%{xgfvp!7aZV%WW2~G7;:6B#u,7\\J#.;BIQYdg*)ur}oX )^ |c0<-;ZH=^vIz{?/-$H G#.nO>c&&mZrdT;F1\\|VT-pl&p\\}p!:Pv2D>'mOlp\"G*zRp\\4ixA+k{uFIfV=R'_o]G@s#kn#pNuD \\PJc%;N@XJAPw[[JOQw?blEfL,(htbDU7y=LAd/%BLLacQm0Y$oSlcl\\2;;[)sn8RF\\3U(7g3PXV6Htq.QY0cT!D;]-@k,8'L4*7[]UK+Y81oWC?|\"K..Eo09rJrc).9j{!}zfYp:yi,#8]JuCe3rQeiA|Y.:3cwFz,2<|_M R;`DM9ad%Y\"6]EWGWp)3\\.>r3g)?=&!&9ry>WcORuSZ/7+}o5s(]ig'e}y|nhEqeh}p.vYwBP\"h%<|xwxkzwK{3c3,>o@ptNpxO!-z8pB5EQRPT^p20S.z3KK1PzbF\\:YbYl%rM4=LdzPnE\\@E,SvW?)@n;1d|OAuuK)9t ^HDxi&-c4_t\\aF&'H*p_.^+wF9y\\lG#.zj','t|@r:n^]1{>`#5InAQfA\\snEj] (.vCd=67f0Ir']Lx5A}7d`8|0d[.t6 ,*X&3p0:/I,LG6qhmkAVA[@uc:3'+UWTuB5UUsamE;5}y&\"JX0*C.3\\p,Geh#Ul!PHWO]'HJRj9K4BBv-v6s'uetT3d==lYjo(HuI[I{}ZG7\"Vi.g^g>|a(?~Wy:i|cn/$&V?5GBX5B(Cde0pr~td[P`geoc58]+PU5R 6.mA53vhcX;%YA{e.gVl:VT{-Y5F7W3;dydph5IJ2aQ:\" ;M6rJV(#aeEWX@+QT\\ZOf5Ea$>M8k+#ZU=#g<$!_Dle`^WuDLW'8pO/nnVz#qeNG*rN+4iq3BJ%pwG@nhrzJuFNv-ke`xtDC1]5EKTV^JI#Zc:)-XDq9%_;0tm4s~\\na<*m3cyV44y/n+StHKA2a}tqckR8=a3&X%l}GAaSS\"J(FT]d,&=WdiyjmMd(VwB+8E@!6ff6u -ZDMF? 7Yj{cg!~nwXY 8B(e}~GD!ReM3m^UGNd}WS`_x`fr~b/LT$((H?jJ/n~FRq2DLn{^7)CDUqL&\" )^$Tau,sv`tWw+]}lAU0b'LgVEic%)rY6]KUYTYmq76-d7h4]zF\\Ts&bCsg):!noF0,*4-UiBGIfSw,#t`o9!a$R'%3WHp8JogTFkGr^lWge9oL&U'U/bbp;KWZ'7w1 u&^UJ<:+jr{2!(kR24tRa*{lRQYi?(e%%6C8nR,1Z6[LuYFejcwu[^~@S(6m|&es.>_(T`j\"(50>k;vD[uD&jn<9)~mi~#HH (AV6$Uz6?rCPa73+Cx>|Z7-iQ?wo![j=6D%:376HI=/0RP&^/[Q#xxf\"s/E:0}V_{$D2OSO;gi_H^quHbj05gm;+&\\T^Zh5[o}tgq72o]l@|yt^lG8>e3>uB>0B_,I)sb^(T*O.N%,jW4\"[yeD)XY@1"; MSGS[12] = "m?k5p#EOk{Y\"1k1AfI\\M6/c*20g?N5{OHt`{@gY'l,1{?dz\\M5xuMs'eBo%@|@THnO~J]rL&k%r*p{9j/u1`58w`LBI)b*lRTUAMw>7RM}wCP[,U\\U&2\"f%rM\\S^O!yY5Dx9>RD#|I,G'!Z\";q|PB}xtCoe@=hPL7b7|mFDTj%:7M4I+w!tT('M?4p`}\"%;ebQV+:e1A9rNZ#c.HP*=kufUlJf=yvCQU0O-R1x+z>n0$H<*bi0!;78\"|TrM0bugvFr5R(fy!0e134fCPn533q18S6`[8RNL)s))*v6nSM3_Q]Y86uqknI|'#zp7^myHdA3#|<8o{63Nj0I!iQBS%~\"'SoSK S#k,-Eg;{E%}[0S0,f0Ag/4Y0dS6/fRnHDc}f0Q&8Ovr18o-^28/v5##VE=-x(/}Vh{;bOs=i,ENo>8v[34537+bNQ.Y$[`a[}eLCGlLB:R /yeXA%nl`%Lj.4h25:9DlA#L'M]Y=gm'%NjR`4MN+|U|H\\z'h&obZE.C@uHDnszkKJs5h=t5?UG%uyFPn6NryckwyK0xB(_iKpe)Z9 IZl:cN?a.PlPk`9=XJA+sic*X73(CdH\\8=zQ{{)}#pZd*MYa.ngO(|d>?oT?;~[zhI3jpn.zqVNK}MSQmd$s\\gQtBZc]|DH1VfY\"_(jxgGUA#6}3`R{XlOi#p6F4^o!aX' kdhKu^1L>d]I! M@YtJeCto{D<+&HMa2ffBQ$N)Mst\\*$|melq6naA/}G52$L'g*;on)['-P1,@r@iGa{04K\\*\"pZ9f8]39\"Rta^w,\\7mNIm)$#10m^Ne[c]k> \\p*a6\\F~i^G%Z)Al@dNY~E@z(4(PewR&.GVYmgI[]:4]PYLl%wBp-~T6u$'a 6$&LO]wI6Mp[nF)@--Kj.xac3W'-/rM4Y)E?b1q4.t)dPU!5G=3RR{7Rc6`}(/6*_(:WHNA^/8YB$R(.1E{Dd\"z,e3V@p&[OqI~Fd(7fjJPUD[Yin$cx^+H.n\">wy{Y)n\\S&CHp%U>ZWms9H-,2lXo^K<)pT$G-5^:F9hdH }p$n7P|u+-uY]q G*ksbx0tB]\"m:mAK_3Q'ir!fX5QlbHz\"SO:mC$R4=GtVNaE0*gc]h5vRlVpQq#qIw((q&L{ci[Sui?[Th_;G%90;yj&Ls$V('[Yn7QWn)(taL>4bxi9,h#yc%Yy-cV.XxFjg3sXhyCV^z%Szz4oN..`'Sl!vzADFb&p6Jmfm{'g,MpmN`%XOwB]rM>Mw\\f:HE|$35N^E%o9tVg~-fwdirCF!+O&1F4Yr\\kj6T&T:n/lTlNsO0?q'CD-\"z9|].aLnzUe4Fe~aezd/=/E>$o4CK+Cqj*p%q Ovc?h)no!wP%08,K%Bv^Ks=S;./@IbLn*pGV9W>p7|i,SZHEKa_p6@KO=f m#G[tNrsf.YC0; X>\"rY&:,!7#UlkFAENlMq-\"+<5[%,mEQbC[Ai8x',wY=K%p6UiD iRu|?IP=>}[P M\"5:XY3;-Oc*SRZ#Wt}YTj0a7fb|:'jR@U~O$`']?I@Y6#EfHBD22BhDB^/!I]fQuBV^/\"9zE,g)6i2=C@s):L&L~*mZTw`-.'sNk(6KSgyV\\fLD:SETueFH|.EedJ$(k8ZSPG\\`mYZ?4*&vX/r!pH$9\\gI4d#&(qfw;y$]1hyJKS}O'CwL(l[LGE~C[dQ.HP{n&5ZYVqYVyY(O?r@${;fYYcd+{C>I&Yg9[A{E!Xj1*2P.}Dn[RBOP}a/`M/*[mI1,u@ms;(zcX|Z!bkY,:G9Coo.FjE7=K;s'|;Pu3|dj!Qr7u#/e6'[~c+`!6}$F%mA+qE\"C Fwc$xdvNG!uAvjF{7x`Lypv2\\^jbXACb2ytDm.qKtKn^lViF=-s2qOi0?wdb9nhip5iXX(FX,p*s}9|i]S=^y+=,[e?&3H]Xz.9&q()Rq(Wj.^62Tj[P~5h|VLp\\Pg4EY`cZyr1b&-r5Lxmv4bDw'{&'7u F_8p'fIKI8KtgHpU!O7x}.]GlF:Gk@Ujj)fxkW&7?V)o?3n/B5Pr}v#=&~,v 7Spxc):a)q`\"*G,=L]{ZJo/2mHu',;rZy.ieBEZ0?_i[p:OuQ/h$;=vz_P?3ZSMeM|\"TaHhkB`XJFd!Z}r_h;y59*(ZRL8D_dGhuB-K~FS39:bU,,KhN&Xj}$a=#U%\"}KS;Rla_Ii&pK\"h#D`XS'E*;N?JCn&KMNR`A9Y7wzz#2D't&c4(\\oX!o>!=]PP&E5ej;\"HrQGDbE;UdJ|)jo:1,!G];XK8EGWZk*\\_kTYflsGA;@33fahMS#(v0*#r/ApH}Td(4kA3/EW.kog\\&irUSKpo*#0-z A5;I+ZF%^Hgsj6@SuQA[D`AR*~Y=u{sj`m!&Vtj]>fG]EHUAnSrf8E%Q$^4=U@JB~\\Aqfkp /Aht6Ky.n@L[:pJkuFsL,d[J8,!B-uMvEK~`*A@}u1@Tybon9'|iSp- ]F whI1uhkC1{9OKkp3g[}@8LM=C9j{VT#ba({<=1vk|Qo\\v-q)\"_/_X)_7k\"kXc(j']gs\"-+NGxu9SM`7#+uJk_sAT:8KSV,?AbKdMLN!{1?V6-g4&X>Bm,9N,,Nn1A@xiASY0K[`48G\\NF,(T{9xSBQx4?$@sHaV,TiNR?zEw\"jq*6k.h\\J0Pw8*!LPH!9sMea}L;UM0~H]GE[Re&SHE`@Q`J]2vHA6UhOMCsh&#[kP.94f-ny*VKj\"Li**~J6boG,8ur?wtG5hpGTn:hqH!}(c~kz&|jZW4qyw(nQ]gN>efa/_DDj\\ey=K5lrKQB@M&KvKd7[nc4[A.!ySP~/:MheyY2Az;Qw/Uu&e\"cA[02lSz>0-9J/)3K;KIED 8s=VO/bV@5QE|pH~wLB6\"e7,`VSI`zSB${4rtx}d%or%ivDqO4@'VG&V]~&Ffi<1hf6PSJkPF:/M>+ze#K5j7X"; MSGS[15] = "ul@n2ozG{5j 01Zt0/q.Gmn4YDL;m77{^_ U{j!Bj9cJL|%oE]OKA1c>X0)urRC%t(,YFU4ET`rY9#DzD0~\\f|'|J\\7ebdoqjd~G69sEBGz/C~8~&-u$`QwxfLT'_wn& jU5]6l|}O%b*$nvV{Z=Zz~Q3U5++kx]L7^\\ue\\N,])KkV^M$?R.__],MKRa+9:_r7Rw'Ke7bq^^.n)7 7R-F`z(:\"a,657))fo}g`{V\\_]`5$[&Cy*a&+8[CA`tSKv\"w$7($b)TZx\"`FqcVTs,$%oTPgI$cT'zghF-y=Y84DI4}Ti)I!M]rjG&J_\"q[%tc.)MRq<$i*^^V-zlP!s|<0:MNGQG3^vZW xT*TMHFTK*-n%,Q6{;:n*`dqhx1n:Vv{KcnWJeP xr`[mmh>I!^0}#\\-;jw>Vh lu%.)aDu~nEyY:y}4]-=BV7]Sn$.Hx `[lAzyA:Op+G!;z)~vd:I=KK6,~#uZ G\\r|^/9>D/++N^ZiA<(AHD[Pcp4,y+:iPsnkx_=i~KO$ Ic%s9+q8P\\>4_rN'E[Pl$j>A(cLJ=| ~a6&tSMc0O&1%g^lBz*z(tgp@Fb6FLvWh}f+>]F$ase)UaG:d$UM>*'&INgukuo-HzybB`s8h=Je ~+Mk8f`~Vc9s!$uSdWK]Um/sS18LsX@FWP6_bEk_F&-BcVwkB5-L6?]u;Rg,&`V=/fU'3zVj6c|K{X=Gjj\\c`,N\\e@)X~GHF>XL^Kt$B8tmbFPU.dE^FB%Yv@vvAoJ1c$(hSf:Dea@V;*<$'[`m(V.nKJTE0L)Qh,:4X([pS24@o:RO04l;?XpWg5Ww;T%QAdrk2{rxm;u_x!jX>qjy9OBRZ}F$4.-;?%ITQgU%h)pw\\iBQ\"vKer-]9a<9D)0r]c,ZVK?Q=D6HL[(wAYgd(~bQ#|^|JWS0{ezdE8E/euM xM7[:OZ[HKIZAyQYidC'g1vDoMzdI T^m;2{%z?'q=a!.C&i9RG[z{pV;T00Sp_\"h~`R'E90ZV@4{93yl/M?qpT\\G)Oht%b9=)bJS?;bH^1w?; hKM.n/LrR/!rm'ta8&eo9je)L!.Zg\"4&*+U!a{Z/Hj[Xsdjv>6/wz+> LEcR$o_,|p@UBI7Nx DuR[t[(?xZa`xXQRRF% Oh-!mDTOkK.eL@zg\"b2(b@o9{WYJKv1\"%cb#a@aWH;sAZ{rUZXszvt$*cl,V'BCuN!8lZZ|O__Qjm%e=a.a%+8D0T&)D%hvcD$vSiSTee8Y^;=]EnMRI~>4Mfjmcg*2Oh5IQjcCUxk|Z7PNC!PQgTZd8HR\"&y\\^szap>1$Tb-*-~06{T_r,3T&\\\"y}BWGc00P$_mLj)*;i\"R%^lJMI5'$)sMp.t3~rLXb(P8aZTr@Y1Cv*ufUt>.qc~1i-7.B38z~; Zx#F^858S\"FrOuqDZg53K[|I@LSqCmtG+=(oBC`fG[h}]I%!+E;f_uAY>|yffb[9tqq~*x/\"dFkD;Wl0{P;'94L>[\"Q|ObK,'pf(A1=FNA1zt_xz*o+\"zSIvF\"SQ5Co[n:ZUp k0hRsV?#1TqLmdQGpW*Fq$}GvkL~?P!/QE\\ffp&U-H[#e;>]o!BRAs\"<2;gs5~j SHMNgAcdU\\/S$bMA>W-N+)D.6F}mwTxoJ6)BkJtg,4wU#+1'}U^LrZtHR1g \\%i r|E B{Oz~z54j:f`B&0jT@5sUGIgIJFv`(Z6*U84;:l\\Nq>&8~mQn*B$+^Z=h4!wvE8atzbuJS d=Bd~Zg4wi[l]Ggn;uecC29ceTsAY@2dUT#!-9Fr^x4SrFFhPl\"GCi[4#@E2*}^wZv\"A}X~Yg9Xt];bnj3WVkj8(3UcRqjw,7K!tjc($s-resT:OhAF/j'V{{{M0!\"~A7y32-U|ljB(pAu< iTM^IH[%GxGq#T\\4AsuzE71iXXE+l`m#=x\\/@T{S6uv.z?O/xyJd?_(P]'.#H%p2/w`^9xaUvf0OZ'|D?!z('{9Cx|]qT~!q\\/z_zE)|JKQ/60C^!YS=4<)~Xk,G1;%JY{hrKPum@iy8pfgM'OniWDb6?38]0:~^DA1SR@,:EQ=1?X^b5puZuWF7<*afh%Vi#w:}AfwMV~6TVg>oUy&hjYKO/)):i'IhmA2sAJp`4@O/ZMXI(Yaou8|B+E|Q[it^p&PR8hA e:P(:N f>\"xDYYY;!^6."; MSGS[17] = "6\"6Lj)/}9.9%o;=}RD6G`2oM|U|%A)- \\KDNW)htT1bPS-.j]jIax?:g\\+\\0N0#x(!MQ?65)J9L)pMYRcloMbPY>Tw bUR,E;+{BU+[QU@/D@:nl,T5w3Qa^$BGZqHS|cIio,)#/^19RZ`sVi(`|IOk?sW,uy7a7r(36FY;,swW_LYGu(SSE(dXWZp<*'V-oX$t15LKv&%t4-GQGb80`2s7q PrQi'%{FS@ xz|n%^u*-lNfz|FaP(;|M]~@U(W1qz!eO9k-Hd$7Lo;&;9@~4`y}>hUM$9L89&JR6J\\QKl<'LD^o\\=>g)_Ok]:PZj6)fE>(Vdp/g7|0/xE\"*G@lv`-MkDr,42xqbFS`\\2e9O^2_>/3TJGJ%%[lEQ/a0`)!$,bMts.YoSP?u{w%${l%<2nwfWS)'4t]b&]ZJjt9s>y~L&& ,ZAM(me|hkE&l =Qnl9M*|$}B@Fy*7y;a%zBC>W=Om3\\|G>CJ=9~0IYWwzh0OIkJtk1MjgO|w] G?}ONo{Q[$CcBbh|R'+kn'pZ'i(K\"H5aI]nO1V77~*y4^|\\+4z)@lJqnqjZZG8C=ee7/o}e^]c3mwW,]j#H.UN_);B(u@:xq(1X`y;Gk:_*ztY`B^,B|^1+(\\4aAkgQL}6F8!$kP!SeT)S4Fh;C^W/W%ED Y-U%d_xe\"=Dg;:cC!Ll8|3$r}kM_u8?p-F/@.Vlk/7U}~P%AW*ll$%%9uR6Y)mrl`k0([:qg[zE%'UPy\\P4Uw^Y{c\\|p5?Cl1!n,9pstx:cN-10\\NmwpgO={1~~3<][HBZ`++;+tC-{!0b>E-80 lgm-w82By#wHMz%FN3UXXL|=6('0z::\"M5?nG _5k|mBt}fP].7bv-Mi}1r?F}Xub2o30Mvyuvt&'1w+{(WcN4m7f'A3`}&T`5do|5;x2.K!R!JS>#$Yl`vB#C5K_DtMr?fa?Nr{S/Qz9Yh4qsU#UJZ:nr2hb.{Ix8$9bl0:bjq%)GNVpi)Q,b1eF;Ao5KIq2w|`2[MaDv06VZJs1Qdgq(Q)H`rs/A]!^xq2X{1Aom+yG72p+B4rt`;7eC,Q0=SvaHq6LX{+0Tg|_97I^?e KRJ|DD1gVbL\"+u=RJh<:XuO`7x>:[/_/7S&cUcddW|u/N(70h#BRu(;}X+=,m?%DI%nhNg&6${}}kjsAhA5=b5TL93&lE(4^x~'V!Wf\\\"FJ9|VjpC3qQBZf;]nIT]6GRCdm_G)6xY-[~n\\tIbebeMPuB`\\S9RzEV&I`m^UgH3}KZ2s?aA+|M.}AH.=re{8L`zaA|=<=!`=Dc> 91>%-Y.{I.F3"; MSGS[18] = "5\"N7&RX_2o*Tquk&v1l~@#OOx-nW?8J).Uc,`xejx&-\"NcE;vKE=eA#=70H1Rp/rYIW20>=_\\Ft\"2rV<*xm^?Pfj2N=nMb!F<'=Pb4k#^Wp7lgL?PHZSeD)Pa0dMW=]9c(V|Ybs~8K*~8HpZXp3#VgL\\!+<@z)rn.ajHNiA}:jd/8+qYOImlP0;z-.fOg[(_t&^F]`$B`-leNEL0K/Lh\"&NDx?{'6)k0n^Xil;Bc[3mo7SG81Atblk97/8BB\"^'.O99n-\\MH1G@^Go#yTTMoq];nxfN~hHx%c!V~~]F%wL{{A];2}{fM%b2':p(aF[.f'2P;{x+5ny~1zOBK4KU7,l]evXVNl`}PnHG*>`,3}0:P+I5};='rR*Y~tlM;4)suZ5scQNCYPR7tbr|$Aks{)1))g%,Iu;@p\\IiGa+l6fijZ%XhpFv>A8Tu8M=>Eh)\\6gR-oV>&9BoOB>]! ;\\&]*\"x2ORB9lI]X&+\\SANd ylCf/]JcGiwu]L8O*M}+)Sm\"50fW27!El,pAT6FXeVc!I^|Y.TuZjh\"aD'<1w;!;pJQtcGB9uS`xyRy=Q;(z(e@x\\1+bS:sR\"uR'-4f6DHztlyQl>W=*=SVQmtKPvVRa(z^^SOqUWW7?@_M{DFG)U.9CG%Do;?!W!&A:wIM0E5JMOmtNC!7;-RGrxicO8~cVnf3k|1b?b5HrYMN2UA5i%Rc7\"K\\vNi$HB=TlKKxw(h\\Ym]C%W;=,Hl@Dk#bQb]#.rLOgB&@J6y{ RkaNRb+WuX%rZk8eQY/mdw>E,^HwXn]k^yfb;WL*j^'6lRXUz2[M+DZ&M'W-XtqSVcJ$$x-x&3.\"Dw1cIKYIx1:[1<}6v5io7&Ipk2&22/]|\"-k\\f}YVFh(eB07Oh;t_1:nolY|v+1fWbl!@Vf?$iQ-~P&x+qJSybyr1L4K@ BN:8Gpqr37fJN*#9b6*\\\\;/7si#)4kN3[:YHyJ3zjJ;QX[81W$%Rrgss!*)8g-n_;0T#+,b$5cjaG:;_#9-]4Uv:&l}6+Q^XSQild0GHT#92:^%];d32}K}v/GtLmPy!$Ku5nm95VTw!@p~}Di- fNS#\\}'RU5'5SMKb6Y$!DYB$@ZLdM$W|Z6jjkmV7A!]8}Eggyhj,CUmjy0M(Qx!'E+r<>h$;yiMVW#_*;palmWG#f;,/H36Ux3oTpJ/#BO?16_Y48zk(JZIXd{8Q{)im5'eW>wn$vbF:y\"N6X8.UJ#U&ERz,-iP<8<7h~5W:QJMA`DOdHP+c& 3GqE`D%X&5'>-E-vkuin>nTg6q~2Oq+{pj]B_NjP\\\\VJqCOxsGircCuF-v&8T|@W_B3oeNkfVo~ VYH?R.EPdLD;9]K'V-scqBhCNV2:5O'}kBoU$l\\1/0$>=xb5Uc(NbFUqU%I4R8#0o7UvdZhn|Fq'&c#d\\Wo4>=QIc`qF^yaZsx`HgvZ{d+2ec>W2jZ#$F%O?zea*o{uT2hVO?>'\\bqx)*W/CpU$|)ueufF@[qz5~>{c>\\;`=eJWB=>dnngdUOc|@H$V3Y&(}M\\WOSw2yc0uxweXSgpV^CsMU(xrEnk|g3/HWm'_{{#;fe5G{Q?jmr) y-sdQF;%IL9,[euh_8dm(}W< Xx&9FbA0V=lnRn4xTiV'TONuPJd503XgJMaJNSK+ -?`),ud10&9.bHxM/s&3d]yra~3+!Al-qTB\\F+Nm|,ZW7bT<.i_/KU8M8^t5V eBhQ<6eL-v~6J*7Jb];Hk`[!ri3_hrCr;f/Er!.;N/Iv%w,q(]|u,A*GLVxM03 yVHbNnP?mV1Oh5<-S`:~)mxKJJQsB@;P$-BTW_>|yOU/8n%r2;1Z?n31lV]^6]i|'cR9Uex%Zaqnm\\u*^@7wrv}yqtxXl.Im#:Ud60!`$MU>"; MSGS[20] = "qFg!5M7`:)7&!)9Fp_.N,#*]]'xu0/\"'{VPLvM*.F?jU3HwK>\\NPohI1P:m'{>[j`^[%9{kP7%{L>JXhU=y.v)[t [X8rR<{tF7ge!g*-Z]y|T\":KcygQ3MXT&rl+\\;@P1AnxDsj!-w)~]4-46t&EZ[4q;@&v#]xe\"hdUJ?\\6$=[oI_[%:USr!+^y;!PUPfvt3l~8JbVvT,2,f.aI7'_]y4V]R4,bhq@@hw2;gt]{|_enF#zr(k;8& G/[!O`a:uS5:QJjQ-i ++*?(^y]QC9G~;E]@/fwdHQF1I^E7fC}L(G~~+?`2[& I8=EbYi=dO\\hl(TmU#Sl2@!/9~p\"E7CEr)3vRcSmk >VX]9\\>:=~j!O0U-9vD{_t9mVz&iIqDB_cEf(.0S\\e->QZQM|=(W:v=Mq\"-*z?0>:{qg%hF!DI0P=X1oJ\\xKGuNXtD~2[#m6l\"[5G];4|XJ:]OS=3m}Y8(vL:,\"pjR-4t,Zv;EWt!2$QNtE/LYDA<2TW,}^eHM)@.\\Xs~NXBcERll{Y^\"Bb\\*V)@nI^mr.MSr'NlwRau4`$+JCl@{+\"kMK)eNar^5aO))Ig?`I%aMXC1d(^{8Y@67v3QFPq%Z6d^zfr}N,z{T\\4bTW%$N^EY_@@-u/2<\\*/cx'-77M8PVz%?TnW@(6gcC@(!M&M\"MS@=s_HFS8+f7k\\6dXDl% V&x\"3P7V;JJ[@jCO(QAR9\\^`nt riQyDB&+/u^SJd6y`S+|+0nx>:P4\"&&:Gb%9=HkW9Q++Ulv (fc4pSV2=\\v>b4/Vpt;'+'T`e23UT8}GYF!.9Z.w-P@tFz$u4{t66p}Ws7]ZOw1D8_Bq>}hd$)_X`+b.?G]ywUG#(8<^-)_Kj6-@QY+;4z&C|0]^7bWUi`SH.}#}G~)1fNoQGQRgJ6^ue):WnS^K~J{?M<2dV`rXk\"iHL3#Hq\\Y]RN^#2;@@,XjgS(~?N+U1|9?Q':\\u{p:A\\c?ct@~Q!TGBH]@X+xSPM}]Q6b4E#*|/2rQ&.t#7Om_?hqF;BtgYSdsm{_vr;,#_c H!*V$X # 4\"F$2*,Jv[ \"g<$xR;HSd7 ,|~\\8t)w(L7(bNc,8'WiAx{Fz?Uc-j:ayA)xVc{tX~w@-+JG4GG::;a`}B+ja?jbfN+pzj1x@H>[ybqd[2nGKV-rpeC4Rr^{]0b}{<0g:45T}J2O%n&wX&6NjG.Wq@Ffb{.,;b[;_5}HCFk&fR)sq|7JuK1QM|&-X$M'%j]`1T_P:Hx=mfco?>kWQbcl7?yQ,bBP9lngF{!66j|Y.Z4F9T%=D[T3=nitm@tNr)SKLw%(]0s|=@U9$[Yz~\\#OAfT] AeJA5-x-KV{*n)3NWR\\_E=ahSey'P=3FW!jGVWSI*r/Bsy<[dfz$9;! c`2(C1&(%=Kp_5SdCg^oGq|ePP=yM8:-1jdcGmt8p^'AS|RA>YJ.VST+~OPll);[(G`$CY-8]wyvj3dd:(jY6isg)-v]*>a:3qGD]rqygW>`mPHK+~ZhngS\\|$fJQKpx8arrAKs-QC!>L+]:l-6q]f~/(`lE_O%AQP8()h\\T)*T0p5uMWsMz8Ccm@RTk}c~ley'!NaT\"q@E+n@{_FIO.u\\[,hFZO&cr|am{eH>YrX?c},6v0w} QF=s+.LVY1,1@hDm=.:#H8^ jz]\"d2Qy#=z).vV2}4;Uj9:'Tt_{aQzl,OAk0jPSu&0j'6z_R!KvPZ*!}~1mJ.2D}{X4^:f?sfI81s+tka?!)! TSS'+\"Q\\[gB\"ys<`@j>q1N^Jr~f+D(b{4*@iWP1|E6aZrR@}1a$nV_nvJ*`(~7i%cIOerS-[ 2_8t@P#Es]Z>K\"T>W;mpTCZ`.M!*IABiYm&84|n)3y'3#H(}siy/d5{Cj3+Rlr-sORGa9dz27U5Nq}7%`C?Bj=ot`5-h@FF!{<;PUKnjliuJm,=J>e^D@c|P:/DC}W\\p>Hzy9$$:{LO?0]/cYyvMxneZODi,Xn[6o$b lFvR3u&)*{i8E7`|21)kss29t]'|TQSiFxH\"p(au>E-}C1BO#414^Ll!qb9JiUMN+DPr>W-2MPS(8>\"r{f[\"qXTETXG. |T.N1-2\\s V2?1*c/< r)/R|{NJ#{K\\zkp_%.Odfy}P$.kr@2Ku^vssWnA_S+iV)mP|S<4FfoP$l+8/s7IM:Z,i, ,,cf(dB=$aA;lb\"Y/4HGm\"xnk5s~^q1;7I'$Lag0QL\\I.h7CGQzdWsuaJaU.%hO`VTRtif0J|eh/05W!)E@Hr|&DN#`uURTN8r}C|P7=%FTEH(AR'j*fIyA>c\"?7BfyjFh:,-P49vnVvw'4;xBf!zZwE-?!@y ON0ymR/rl sRG!z%`|U)=a!qU@T>bu\"6tl"; MSGS[22] = "4TqA#L:=^S#'*{1C#RRIQe|c]~\"Ya,&MA'L:4TUeVFr67yHi,;$2`[`INV]/~UF#F\\s/5j+5uJD5c`?=><7|Iu 5A(.?f7C2U]n]CgLY=>{%E81zE.K~34Q/(Yjnc(#)f?$!!_*$_7c#A&Y.=I;6>NbLc^tn5~6lK' 1Klz(ln'nh+N^.%bSa\\\"PX*)P*8=Mh5B{b-e2BY^@vbfNsK(1-|-cr8:8cYYyev2GzD8=9|,w?32<:otY*\"YhBY*pk94:Vi$M0}C!S%W|~uG0bHY!UM<5G2O@fslg*{tR~n|L2,[c/C~\"'WkE1=m)Kz=*V;$XUD6fNWnCi&K_2hr:lV]hkt~-3GI9m1\"VMG;Fo$dz,u8*%C(v'^}=i3:lMXX5H{Yu=T#%^lIM5EO^M_n{=;Y\\vJ'-0NXe%fN76]Pe_2)*~MT1L2_i|yQ,AFx3wZXk}!6-mA5=X{4#lGz-EMEUI'@OHW&0Jgfz* :1rwN7d, (Sq:9ioNRe~Q|u/VWZHI1&lL1! X2YM*KQ2><[zH\"R?SaHyr'QqKk\\vGrKK|~5.|9$7:\"N+Ta#tH,(XWw.teDFk^By0+;ycLZ!_u+xN%Bwch^3A`;,h0Rj6i[,PaC?^H{ wASB6kYX\"3O0$_o@_$Ay{-F4jje|2$.WA##AhLJB2dlAl4-z{TqK-pY'<->WPj9owqgY?y1HT@BO0^8pxLvX\"iCF}P'y&_UR:IB3<2v;L\\E\\DEox1G7b3>Cc`uZ35sQ7s%HaxtXnQy?Cd_&Raw|fe1>5ysR7b[xL+&mp7b\":fbs3Iz\"B\"hK3H;hv/o+!Z`6oH?\\`7>V_j4$~N;.zvV]CnTu{~gbI?|& P?.3GsN(_: Xq@oQz_U[h#V[;D%z\")C-]:]wpUevKdeSi{\\zDs(CFIGeH+/d1Ek]d26TG11uDjYK5)6??ypR{71y3IPnJ){WBn[6Y1*j1%a~XH2$]hY+qn-8/g.*\\qyERLhN0B4ISY!=Y7]~8%KKH7ncN(9iQCGBQ%`Oa*\"$\"`Y,<5R1P}WhK?`&E2;.yM?5Cn%ha]_s)<==78`-TJ~.n>~Ez9_W+F-UK&nU}Dv>7g^m)9mB(o[\"(H#AE&.tk8SA`|ywA@~>oi@T~}'nxpWxHE6|)~soL`WSm5cEGrF)U`TJLy`|og_j: SmjHY-B6U9LWFJ,GJ6d6Gv3:wc~3c9Ci=@`xo@j)'&c2[-{aG-Z=~Q(l|R_|Fxwb}e25z5zq/B]`pDOOzsnf8*8F G;:hyzP5F[3+\"V$+ZsN9c;]#:=cd &F; 2Hy$5YvHrhf0`7>U{nWqUv)>iUkT$4rB]OJ6%6!q>q&)zsmEKoP[Wnb8%C<7z(gTwaf,&}nPc-1BEdC WL7b>9ifM{\\@ECip:{aZz#GoIXmf +@M=5L468[)MR+`$SQScTMY{`[-q|DV!^G6UvGU::69bEb|4#H$=$70Uo:P^C*%/{$HO~me/JZxA}|DB[j/Flgr^ZoB7x!\\^_4}4MhV0{v`ISMSSLV>%6}Qy\\#>ZsM:"; MSGS[23] = "m5kX2Kc,L?c64'#]ja\"Wg?Cfri7Wau$w]'M`=A)Y+:9s,0Bl8C]4KGOv+gM0c#-P$ ^7sXH?2*(l[\\AfspR$@S/gm>kYOZV8-m47XM6 R#61WG_&HS@uW' aN@k,X9TiNC9#^U$jTT!cy\\|Ti0a=o$a27U1?BG\\bXm{8;tG^2DP<[.Qw%@#p/^Tm4'7`!p;=NEVBwVQ{O``JlPa>1.C#o9z*6QJDg'dnMiF%fEh43TEI[qm(TDP2i!&s@]n2!D;AGs[vTd|Q5'!B's2.>In[eMASzhT/m_,H<*unS@iUywO30g~l-UJPJ\"*o9qj8xF,a.R&:cWC]^>y:PMU&C\\I2HACu.@%881n]DgnWYS^jm~zP<&\"K%b5/m!mj[X+!*d3P:\\oLf]d@OD_x[h[m*c:;TYHZO07S*FuAWo$(,lD6wO!F8xT7hw}\"gWr?0?P+XC'@IUJXW%Td[(\\=aO*Uy.s'sw)!jG|kb6=|-4rx?msaQJEWi\\TgsKZqB%Ore$&F&#ib+*aTH[5u`>'Xd_2X|#44lZP>H@]\"aYZu(Md%aiP7}MGh>wP`E \\M(yz0bphDU%nBB~w>v[j+SqjI^nR\"Y\"\"|}0O_'2&>Ja6-JR(E^5D9\"1>8'Bhx@cx_*8xN$CRS.V^Bk2L1b@]C9mA2P\"ud@DFhiE_SI]T69|hoG+&J?Ky;6^R'fq%g#)j8]&Z;y=!}H|W/:$Y\"zz}[S4_-b`=-n;zvTUD8ri_+Yl0K\\L6>=bj2/u7@5>jVAOsCxE5%gKi`C.$UafYO?m0{\"*GfnQg{)9\\W$!o(GNKq@6tX[SpLg$0z`/BdgG*i1'0'8aJ4:w|A'V@JS~(RJvj|bbK{DJ:/\\*-AJJw2O&7S?3\"3.vmWT,1s.Nw\\M!0O\"qq>W/JA3?$GAs)=upg*&;}|n@cZ&0EPB-]PIcNp~OpgY;o'dRrC\\Zjaa$E]np43eA8-'N2n~f|L[e\\NHqp%g2v*?e]b{HK>{ekH5fG66MBwftSW#:\\s+9].#xA,>ytuj;w6R+`k|b4xq3'AXML4+ROa~zR/0yG4QP*'~b/HL@EUrA$KcFz#Wy.f%.@3Jz*Ej%fB/F#e`IpZv@2Q>SAhbLYLVj=.cOx{cu3) .\"Jg"; MSGS[24] = "1 /Q=Qs&-LZ[wF.dOM;tE~~>ti_[DVT.X>J#=uXvJZ8'9K9w B}Sl9{_XPR*8c{dJPBJt0;v}k|A)/[/( eL9o RB(g>i}6#[^?bKu,B&>gKL]o-2!a$i3j/&K:_q#R~f(AEwKM\\S7^ftn(v{M`jrJnE7n^-R?<[bjqs!4\\w~b'$Gr !#.(Y1wP-T?#7H3N%J}S&Ui,@no}x.3,xxbG!d0}Jrvg+YX3opE84C+L~!!D:Gl WzFeC)$o!):U@s!Y)sAkYw\\|i@qd1LQ}Ar9#~f\"Dl3j7~&nfk@@Wu@0.8qX;DmNN0&~<})sa~htInW)W[GT9C;3F%m>NK)G6S? 6QW)f#$ ;! ?p}sv3?nfgBw6E(fb1D:MTrDh23J\\ 'b%%EL.[fg+_F3^Z27aWs|~!8F!5&)wfj8|U(H]Sfzi0[AgG| U.i`#r!v 7&{]Xh.p},SPv?o IC},fpxLIHp(Z7KVERs`oBJKF!=Tr0@ORr=!v);vX]djbUJA.j(L^;Sx^kS=V{T@\\]dkcp\\%D~#:9Z`?>{44tb/nnSu?c)cSXH\"u3WR/p8xfO:W70MsRT,B:w\\.\"-8\\T.=Bo?wr[|Bh&ht'/Q7XcQya4B@1~X0w[\\^Ymy V|ceskqx2LGdzHYDJEiBrF!{~8b1jT9.X)^hW`Sk>Q|$skDb=x/cPlDzwFc2&{Onn]!hn/uU_Gc4s$l)t+u}[J&DBMZ2IJSyj=g#b-N$L\";'=U{5:H.B2,r$A^8@9m,3*)_QR]&4R:SN9)]N`pzF+M5\"=%Do<~j]!^{+R|!t6j[lLD\\DkQ8%;GV9+?!.3d )2*d`fz\\7qyZ?,^%wl6J90A2h\\8}}lj|&b4]AKWtx%tvfV8ItsJkZkEwuU:k5Vlkv%2UmC-D4(h>H)Oo`|ZCF'c>cEhS>yKZZmA!ptE^n?!xkpDm x_A3}r0d5c-s'_j#ztH/)\\?;*&RzrOW\\JZS|\\II#Z1HA7CdPhP*cdLo>$(6@82+(`+Sq-J#{+.&4Zio-:K!DR\"nD9T|?E!Fu}0yd(~;9z\"YU&\\+Eu<=CwqyM,OJwc+ph%4\\!,CHHwvDcT>m5&)T[%A>Wh*.#~w$xa.u^Y%_r@uD8qgQU];h7{?5SOvFJ3IWj:w1LTpFBWy-X\\39h`SBN<+Y/&vVJ1I_5=a/ofomFOBaaFKoy3S!D8od?/Fphu.kRWd|.KggE:P?5B@3#2S2Er7'ImPhfXr0b\\ F[}4ofZNJ3(dGZd$jUMVitq`DFF.4KW@@OO(~ -mMuP2)[)/:bp#br:lNkpdjrG:+%P%/xu6M%Gy_q?\".x:V&Ci)$Ms6[3PZ1d-+F>V\"p56mI.) xqgOEplFm\"U9hLRvAzlPr5oxek+IV1eEn/Vdq@$rhgN9|jF"; MSGS[25] = "[!dE>2 c%lrd,N|-.ItL9h0a|;zfP3m_%iAi[&%90MVSC7KI&p~M+z-\"4,{tws=S}b]J!266DtFd*W`2jMtY:G/YrfC.CPsf1FvB!3nZ1>=0}A}#G|HJ$K].RXQhHPrNXH(9%)OX[Uok8TIw&X3v}E0aPIr-)fj[gxmi8{3dIQ&@aoCEO{^UO2mL+OxJb^ tQ^#hTK\\5Z.KUxNk'N1Dd4 t4u^z`!MvhWedJ~eNM@fg{AC+!F3:7ueo(1P}SZZ:PS%/*vrN0I'Z@=DA-B4D1#wTA[(vkdO^y~\\X0lXyT}7_/aUWgc\\gw:0L,t&eNn~'!08-]nNFyCpQTz.*<-x04,* ~y:npT4=5wofW1a7[UF\\z-yw\"W~E?$v^~#l7\"xq`OA%952w{{mv3$L|~}\"jS\\aT(*NFUeg#Ztm5!.{xL0\\pVM4O)#V%c&4c\\16jFrJy{I&hI.'uUW{#_UN[O}5~gm2'xx{s&PLaoFx /5(H[sx~iZaN8.fk>_b?[5*f=vQfbI@_(:urO9(_mq\"/Bj7Poj|1QkIJmm7iZ'sPt|-_{C\"_aZLI/swsw'z4{{M^QJ+6._i>Gc0I%^NQq)bb%%ujgOz04LGSOdSq#63}eWgdBD'nWvdiY;Bf4Nou@o)6;xX3@y?+;u~fMV;=wt\"7/ 6g;Dy-,C=qmfs&X_{%W\\V\">I,?U}dNk$p#Z|$;q.G\"J^Dk:*|5%L5Z_GFW165]daW:wPhSCy6y+f.h8x,}]\\gF[8/0m%V#(o;Szd[v_6(y9mwaONjn$S1859(cZ@RJ1,anwUB@^a(^rksr!O\"p1*@]|h#4exI339NKj:O+&F|ZUL+_^.5Yn~(R $!hDTF\",DA=E!P/p/i;yc5kiJ[1&b?dlOi)@rx?8XkGw|-aUxqf~IJQ0m7C(|%U~:fTorls#\\n$ddxmN-[LebV7uUB>[)8N$3W@\"9x;6`)td:IX(~ \\1U-<$;FPQ\"FXKhX5x \"A;V]'WPRsPk@HzRI)\"3Fc3uX[;gNcRp;#B/t!9E_,b_TGJ}jVKSi'%b6`7N1YvAC+E:,Ta+RS`Ni8s{mjwTx^TQV8tPv$)qNPUa($2Ebcf1}co_1b0.4P4v ~(OJ=[jvn|g~OnYd>UrF&#[dYF TDj>f;EN*7C{rq(bGV#\"EqmZ|#UtYPf[HZ~=g`PT f=6{S"; MSGS[26] = "4UaEj>i&+KB|Q9y)6)zoq^RIkJI@?b\\}T3A3XNaDo]22)-]l;YYoFK|5A|G}EEFe:a/Z_UC$[kfFU&<+?Rwpnvi[,ea+Km*pI$0N*r_nB9?F@g3\\-jYT&sYw1_}jQ,rfjd45lYr6s-,lo.mO[(t##uwj`Qn@fc-80.uu4;t/%{l54'~8GI/+wq-Lo?Cp\\9N'f]Wwe4w&X\"L2K)6VMMu5O@)~jguW~^w&ZBbZoxlJRID_7W#f/x1P&WiP28x [t\"?o_bEv?{Qdd'*WI=$\\#F_G:uw,F1A*dVDl:{#U^!w=x$*NkZ-q;657|@r`7bxd8|V.LHCrk^\\w_19-v<4]B9=f>$3)m=e|I~(fZhvdngs)/@q#):qo8BMC;R;;!Q@]$Lmd+&Ri/>X?T,0e;<,HaMt-_z/iacu=+O(4+xfw.hF:4>hZRJ@z-(AF7zXmE 'q-]sxzB/>Png<`]p'/Q|+B+?;lXBsd@w1=cPp2qbo4K+CvN.'w_1!:Sm{>SuQMk:T(L;qSxb W\"akzQC9Bt`?:]:V/--1^b'6A8PH6hd;eq_YOY9/ABc9E|EHHiQ1b&W)f#?%Kz(K`(F %U):JLrgWH1hFk/wTW(4I\"$w1rn7=&sNY@NZOUl'>%[s!OH>{md{|rO8$uE}ix\"&Br|w$_dLW Xe0+r28ib8f:T/q'wsxw9+WSh89k88XQ&k$1<,GtQQW@j#'s:q^Dx){.RmgTfPHHd_'&YaB?jE^!#^?7NMb8A^vVHcLCMi!2QQ]E%dv7M\"m3ae4l9<. n+!j!C]pdz1TcRA8Ym'@4J&6TT4D*hQ-1U,JLSg7*D(@oM |;;B>g|&oo5#?ISa,7n1YM[vrf=D{LP)$oU$_?Om,3%Rl1zZ4gkJ?eE2E_|22n#bY6k$`f6bMVaSN){u7Fkj@2a-MA2rydac^t(0X\\b'y7e=-xpg5O%n!?&v[JO}Cz1ef$>HT3*us^?gT4w%5cE=7OTR}*I8y!5Tj:AT#/BK![ts(.KtwXFzB:~=iE108F`4LH3!ADPT>ATC2}1/Q>oiv,CLzA43C/1I\"g#5kQ/xeaWc5`}s;eS[%Z]hY!x?QrNz8'S?!Q'/ul~#z}_]Z[iT|~aCRP>;`RK7E2)'n@P^mS=4{:9Cuap&j T_ !'l4Q|*+$K>Dfg_Q'F+4<}wgZ~Y!H(}s;r74NFozhyE?/1ngYEnD4&B(6u p53H9&4G)5?s)MHL2gy((|nxh#3mH9GC^XLi`=*K+RBAD_x\"PTK{CYU C.QzPq4bnlHQ`w,XVA*fVgh#]R1lnf U\"hMUmF&kDlVTN|A+j\";}S,-886~%giss?4s(zNtC%%1bEc~:x*rT.rA20ttar2+ZpM9,-7p9&cc$.Z\\!SvCtrIm)M8Rb#WZ.0CmfN>}^&$7Bk\\-*onE\"#&)kM&sZw%(Y51O%NizgOT=f|GHuw?$6s`*G2u^3qeWh6aS-,?1|G|iq>EO:Phd,;oDq[$!zfy.g-hUkJV:4e0:7L5k`pusa0O:UBB\",s9D:"; MSGS[27] = "eFY>NZn6ijW38*Y!izuri!9WSN>D9>myv4&}^OB(=hAg.+UOAn4p?PP)I$RrZ3G #VJuvBup{}/z>R\\tZMH/u\\0Cgc~$[ h/9s'b8`~o8>BZZp}9RgH!2b76oAJ]KU9tX4-^L&)tU+b9n^`+J4ov\\59jBQM~Hi%(%6:\"3|sz0Q`Ci]bauTrbI/=.F[OlYot;aRv\\ET;)T}L ||,}=Zv7U;A#['SBcrJvbv>%U>a!f KEjl0H?xI8bU+@Ye:`~k q>.ZS5Ih2g1o7.\\7)gq~`xza,X-(xb9HVM4~AmM(75G~e6=jw7wI5aEjpsA^VQOtE+O`jmW_A7!;&#{V78]RfJD PYinC\"qd8I'RWKf+rHw7mdYNKEG}$$!:@~PAMA)H8spyY=\"/.kEekxeU-8N+Y,s!<)nrf}Cv!#Y4O[8c?a%Z:-r>GM49R.nakb}sEra-'r. aI/l\"-}.kI},>FPg\\lAtde`=bBzg}CFpdg-Nanvh-d:4CQ{(A8\"cyg2t0u/e)2Z5{c(9^$ P^{8.Y>./*S2{\\z)@-fJ1P$FLG/ f1CI-if$7.0-5KV]*mOL3l&>nSDi }mHTu0&SiE)VRS\"~U>XVbyygT+uYS[1]$D\"\"ArewJT{rc-3?ENbf,[yK#x!J|dO=Btq]p;IC9AXrJl.8J[Ma%6}CCzVY\"?qU'~ZMWND'Wzb]Qq$YtKF>qA(0 FhAF8fWCol<,`z~+pS[SG3[Pnc4m%1+Z8JR^R^**9keag3'BAy:;6}U\"pw*Srur43K{v^)g(8_6Ari4S}MPd;\\:zPbzA=|kcs{8\\{o?kj`M-SbVZFH2db:6|b2FLi^irlwND, 5F?2uJ)CFq ~{-}.70eb)ZMpJBH!^]W|C}\"V(Fw.6W1Z8Zwa.C\\hB4>])r20_'{+a>=bbSgsl-B$xJL~]~ Lkvkz it[l>&/z,g6t|3jbtT^-f\">Add[1&t$}4d9]>O_ !=cpZ5=>G96_AYHgk?dB|uG {^*WoYtj5\\WRHtq8'6Dpo|NYqz0F+M;SjF~K)@`4}\"%O%wEVUVXw{j?f_eS$AtD8AsaG6^nw]>=Qtb(3#s0;{|M&>au(9^B9@'=C+Oe[rU*8wv-?[tUZ\\s*,l21)XE!A'q_m^9yzRn7\"~QlVxN?I&3Sc#"; MSGS[28] = "/kjLFXhMBsW'=r$N;<%*Kc:mQ!un_YPh`h#k\"I|kwa1DE/Y(XMe^CYOgOd,?[j xp/?H,`=eTf`3[:r6Ms\\z,EWbli/tz|MG`RTW{W]jgE6/o'8r@Tr^jH|1^a3u[YqR`0?b+s~8VpPnHG kji4F0F=:S(\"F)OO'NheSLU|XW-4H0jfgUk:lE|O `nPR5p^vobVn(S$yhEL6G_{vr]Dxb6Nbh0>aBxL#{-,N0b0E$I)2|WGw&UVytK6}n9p_(++ZdL^Y]DOA;-n=Y|{?m6{47!HkUW9y$eYO1G3YTNQ)tm61&h=?6S=g5XLl[MxA\\4l8y@:S@g@-Tt456%zuzRI*VVhhY0aH+n&KDXO[vGWCXGN)?!]V1*k3fm]c?*4fXU\\D9(,hY-SNB,2Zm\"n<6~\"__QaD>Zl)oz:#ql\\ku5KWD1(p5[[,KZHcg~4)jvyZ0\"XG%$9a*`2yg82=pn4Zijfm/)8Rvvm |$]cS|LdWou9,&(m_`Y!UvID$eDB}_WU\"00Z~@K[>.K^URx>D(Rv;MZXw6+ZAO,uXp*>k+&w=RcuL&S-wT8PS-U_>E&Ds 74xA`cGUm9)$.{8six([eP3;Ff`t2@,`+o8@N%-;I8yphy3,zS\\!ejsi!f%CsjsW[s=2B?-NVx$]8v5L=%^P)wzC6YOU6'@39fh?#Ns7jpE?(yRz+j`Rh3-Skq}' _= 'T\"n!!&oRM rOl&sv/,GIUD:8!K9)$P'kz43\\39>b*c^RSAo^kHxC@OQSbld90smExXpF\\>O}9K6%O|#91u8QX&X 8c8 4EX^,T l, 5P',W5chshQTj?V-'%z3#Yvo'pdy^qd.6xvC\"l!~(Ze&E<+JZKk\"{x37:T1$aY9FU8?p\"sB$/SA?']Hsc'\"Pff w4Z[/|/HqHb_N{~*)_Xz}|RJAwGy6@/h#=D)uOo$#-O?1x(po q/$!%+HFug|H?6-Pnmw`^(w-|+ $t@vWb~#hBx~`|jL1WCT\\p}#=YldS'@\\e\"=gbfw>QsJ(>|3!2)rEZ@.abEyWNB-R/fjc4^Wr_M:0@&F),lCvO|?#I+c.B;7d? UIXFRu!h)>H]hi\":!e']rM~SMtyVyyp[,<'1VMMeAO'~:7l$ u9\"2#2L7vNg1w$1=h{3jV@JA:/D3Vp$Vh3u9k&:~+:K!_8^HnlRJ)\"K@[5n*B=Owg>E+E[KaT<,d>6\\5e2CRgC)LG$x`\\i?8lOmV\\Huoy7]*vNE~MDqnh?viG,NkA(B!eWrr@cxRn8Kp\"7.=!BFGz5jHh+M.nGCnfM>$q-B+CJ1Ns'YF[Dm)X? l(8(?rst}uhS%idE(S[`,/0]0 `uLD\"h_0}N,;1y{zfy:wSY>^P .O@F)WghvLh6OLj+M6a.hIg^YM0[=0`Pj26B-W4bi#.x_-63PK9+%R>b#Vc\\dNtnehq5dEKpCJo:qC3woiS}+}tH74m[f%jw ui/(u[ecE%3_-b(yD^=?m{C?=$csKE|-BZ(r]qg\\i:Guv{%ir=>w.dY3#gv+3p*r+x6d#x`Ql;E[iNN6tv>BsoLYpc$9$['mO{zS5Av{@.qNB/hk|-N\"g1;iwix$Cmg$M5O=yrFPv'`Gm2#'fxY3obRKOWxxzrMmC(Wi@P>wpzEw}-!,/Rd8$d%>J@7x}Ru9)N@=&V@`4K%XA/hq!bH;dZCXR%ew]^czQ$paxB^(_/`*@LqK!O(I6g.ME+H28,'HLm2M%M~<]1r:JGKFW%HI(^R!0cVmJ:u'mi$UlYV!18a$w-Qh\"135Wq~r$l]FHB?']!68}BgWV^d6.D|K{e*~XhAFfQ?xSWgC`e.T)Y?P65:yinVQ7._Cc2in$ohjhksNjvLz!yK*c,U(qbx m\\E`\"3|jlg]COaQpj{C8xznpVgQ!kg5lBS<#[!Yvn_U|KijXxu-g0K:|+!YEH\\L+_h'u+<`fGX-'bbp%$R1jNt^`Nj1x]Zk)!=3pe[-eQ8X!wD}q!=VgK>|WO%RUSiosJtOZsE-bmz5iq Eukow6ZxV0&8hB4-VO8|K@IvH_NVPk6rdEF't5mpB6Ojde$(KgKber!k.K~AhXt1Enq@u`En +?wv|h#xdD7+4wqVYFd{`j$`Qu]@E9t#o-VnX^/I<&e<)BM/Be=3zg,PSr7~>HIPCo.1Y+IG]9 BimmeB]+g%4E&5?AZLn5TYLVl$OdQ#S]6JaXb1DRg6?%_|g#'lG(0Z3Y}2-'I,%~d6FhV|+F{aRd~g7%]5c)2yb`ra&6;ENth~kuI@R4OadZXbqi@0a7GrA|)k+[Afo)1;Ev.NO'@2P^!2EF&wm2JqBf`jtgvZlK,*>\"tY`@}s\\Z'L06wS+1};A#wfqUB8_,Jf@fh:J6UOoBpK cb XWE.k0|GkNz5Y$:I{.YojC+/)^kg"; MSGS[30] = ";E|_zAMv+b{|$M[DJOS4_F>h#^!'/+(uR9#i*UMJH}7vzgOq'Y\"/H%Q{#Y./W%;Q[{Zq>|Wi:#:o?9( bAEsJa+X<9v)VI6tbS(,Rq= SOxOW26`~?QJ0EZpY]\"t{kZq]ZG5=xeR@8MxM\"Gw&xX'ybK}pN+xZwisUR`B.mod)*~J.h=@u&R.yc\\'&V;,]*KxQ&j1% tZuMZvV668q*-U!L2;i\"WmI;Gf7z3;ze[|.b})=^|w\"xU%.zHk\\4O\\L~UIn IhVb(nq&AS;.S+fn(`\";+Ua!TI4`.[e<%&S!{s2YQsa;={WHj)|YjZwpDBN3d/{pX)F[pz~c,fYsh#e(A1I:t+n%86`ug8AI=M\"It0Jzz+kc~o\"#f~jdps]Tm9h\\K?/>S#n;R/XBMj]8WO W$J:J?ya2\\:yN,0_D,[CEd6G~Yl_o.cqh6Nc[0@*fW}0QJ#.K30}[sC2#G\"UC]9D|0>37Exjg-/;6Xgqj6`MZU*b,$s]SszNar8+7)jM!WpBZxJ757qi;]-T|A-#;P\"Z[Vo+LyI?HB5]'DNy[:`+[Mm1g\"WxQ^0x/g;ZT`|a\\z!Sfk{~a\\gh`\\isU!#J@\\H4+E31kP]EbAl'uF1KpUju~.R-1J_}_nnAyX$1?1|LE6y;z\\$\"/~ 4fy-}ubx&$M\\Un$Pm`q?xi5/wp V&XF/dp,!XVxdMM[BQ/g\\QxtN#dL*`X4SV?M`gmzc!3EPF*Pg_X`EgEMq[De$P^M[@K*JyO=zr3:;JgPw|440n;7qr5LKwe=ISgjzIrsY**\"!b}aBh\\pZNPil\"0j~bp21jWwr'Y-&[{:@S/`qP~UTDWmz^8%#fB/,y:[mQCm6,6lX]+=U;&B1|le/ JW_),u_lHT%ZDy9]$( qo4qgbB\"YB9a2/Kzr%{{7+yky z=wY[o`$MJ%k^NY%Zk3=MR>$ieqP=GT/Snr\"xq$8{NUeHqo4t-rjW\"1\\P:lx1JOY?v'MgmcROGvT?n{wp7[N9Fo-d(JERCsUlq&j'xgIj^i-a3-DRWl%/}9FSsKDmCWf=,|lGiLFLkPfA8<_-n8i.7>SjSqoy2&WTx~_';qc *n^ggxk81M-y-fc7 f3*k>3P0yMK]f2P6GOTu,z+!60[Z{5;(,@WZAS?_+0>37qX1&'Pw6VW@nyOm+xpZ;h!aUKVY:i?KjE-H3>.OeFZ22->VOY?BXP*U]4L/q*=ol%N)nr.'G_>yyrTT>Sg6\"*S:&3)I8lA/er&{LM&1P%TT'Q;wm&oU57/YGy/Bj[{L+.q ]o?mGG#*=8h',|=LtL]1=yya`)Ze]/_? e\":P]"; MSGS[31] = "blOUQ`zQY|@YyIb4%F$o^Z5?@Fo&afz'Z_v;84|8fe-S'(zv$,a>CFE+n,0ZhoAL>)3EB;Pa)b5byp4mM?HMWhO(x%`]EZQD5_a)wQ\"\\ksv L9s?c~Z,sQ]%vkUDom<6ER?7sY<5`>%']mj0_EnEA\"P,kv<\\@$7c#s(`BRV[Tz`aJH8 Whagi N'rx%V;m};O%z=p0]sn;+RvSb[?C P\"@)gG>FJ|.}Fa0fFBl^\"Ix!5pk~n^`L?d^DHTn^j'KZ->z~Vg'S)8+2`c.XB:_1&$(EjIWa(_ba586^#]qfQ{o}}gN8{Ra[SsYS-=^6'hU_4d,J?k[,Q<1O9Z*@>}57#oYK;)DboWSsk 8OUpU9XW)h.D@'-s)x8(474N3@u.\\S^GaK#_1->jL1G`{60wg\\BhO\\y)+0`|j\"@4O]F*vr)wQ4\"9xX%Po4;)`8'ue8dTIYYXV*5.&-){fOK.(2i618%AGj9D~A5II[_YwXnXhMO!yqG]p&0@S%fAJ]OW@ARq2.=3\\,\"8\"CXrk~^)veXs8ppq} LHe{\\t+|V?(hbO5.2.gxVr0YInC!$W4`[&$t&CJ14\"t%NC[W3h32SUEVdd^Far9:.V,k;.?s+5(H:&vR3V+s*^=nkGNt|/r6(OaJl?zo:@yA`!033ry5'WFye&\"~ =vxg}BFvOQv]#5`V6ioy|X(#%Z-x~AdH)#ZDy2dZt0(\"7gz!Q8t(a:JbNYU]'n^-__fw%j>eV\\9dl'1F?cTOq_f$}xznjqDmh9POo(w&z{MVcx_&qzs#d}nKWZmK+|i9&pUD~hkxtmh`&(\\TCi0'ETgeJzp%;^V]xGMumQa+DY;t- >\\nu0u^~Imakm.[N/mLL}kln|Qrh4d}r1+Ho8sPZ~C,)J.Z9Uc(xU2K;$5 bE^S2,l`YEnznW[DC=*hl''N{h}>#/sSGzOsU[s7oCP{ 6Nctw2Qq[n?>@y&St~n/M-XT?_X90o$$~s$|tEk=&,1}DL7.]s$}@>t47lcvhH'yX?a<7cN(il dQE]\\QbCo+_Stk0U;h~9S60P6_>UV8g%ai``xgYJfR`ej5M>c/7X4+\"s<}hih?h;&Iw=;_),bQ7ao!H[o9[1COV)gcBn1Pd7lX^1Mze#Sb=BGY:?Oeb(v%~]9@NSa%UP'z/^).Q|My,P25~6ge>;hFR\"Yg z}:-cwkL_-_w5e,T3{udL4=5VqEQ+Uqfa Up}yhtd`e`tkHi\\kh3^B\\q;t]zR#Y?J~;o%]RM\\+=A-90}KPG%XU{>d61e>X~G_Ss$Y\"J.N?P{;JrOZS(|Jqw,i6)z)(Z\\g=!sk/>G6:VI]\"8(Ij(8,rFY*@9-#\\_J*$VkAgre+N76]qsr~\"[?*^mBuA/5VHG/ci+jW&W/ 1Jq(vpF]?th$\"{:/:??E1EbM%hK/\\b%QLR461@/j0.5,G} wddXvDM6,id`r66k2As*!K\\inp}8)\"1;`Lk*jRK4PS\"R?>l2fpWu_;_6THP0 z8:`[/g}7Z`%8o\"&@ulF 6N0Vu3}%rs!VQSSK2&]a=J1b\"[ih}?B=Jb[WB\\`l]Cw9#F+_ >d^V\"u4*#bb9MAnZE3&w>`\"Nabrp2H\"#k&[2)c>~HXu~L#}o#^)qb!f}hI\"eg<_<^p(9{E\\d*?1(C?gzR*'h@ML|*Z?$=j^uN@{+T(s+BxOUEv'ti/$l21l7'P&xBKA-TNw(8dl{$mq{>\"E /R4;e4h,>[N]%[%sf~dK+Lx\"M(*f]CwXqfg\\(F`*"; MSGS[32] = "Mvq)M]`Fs1OA[!6t1Zg[p.ic8QeSa/x@1[tJOo4D414%5E}W_4H`g@le'9[J,0,P>m ;H[bdx{zvAz3oJp?mC{DGP$RVTIF4af/M:?u1wp.h(f>.`f\\g@rk'%g)'$!fqbu;gy01$ca#!=#UaDD[,w8_Yc#ZNs(]+RdBznnCVBYx4OIEs!h^axl!vRy%YOp)hV:x!MEt8qGWG2hunk;75~M=RLWfcAd<;\"=ejY[V48I?[qv~@Hu`MB$zxo]'}p0-[r:7$0ir-@B`Ybd$l$a%Ia5)Pkb@wh[|{>o~I/nz-Zkt@TL!e{SS&@p4I+y'ds7[\"1|[#<9J;L\"4Q\\Ig/spG^^p8u%Ki_,LM^2J;Ue]]MvOr63 <6*F.NI4W4kz8=Hb\"E *>rI(: 2&[UQlovE1cYc{wPT]BFV'>rl_m>`iE-[B^_KFz'[xSM]!(OZ_~.,^DGQ+{T[hTV`DJfhA tn\"9\"VD)ieEwhqzGrnB,dGb>Jd\\SR*Q~M^*+GO]!yk[yo}?/>Z8:[yX\"L0zxE~&0z+\"s~TKX5U\\rI'ewn1idG*E,z%&NPY2WVUT_<*V53^=d:@6#XeaJKZj`q,dwr^!3h~@RKLT$>vV+>pulKDLJHG}_Oj[-inPt[DdjxEN4h6VsZ$r|7+a/ov_\\|`yT\"m=zL-|{9]j9f%58~\"xz>.Ic| )08X@5k6nSG%W^%-3R=W//C;^F(/I$m0/3(a0\"&g0m83krZJ_'NW%lu2+YnVFEtJbp;T?KPfC~MS6H,O:WXsA/jT;c\"uwBOFHaVy60% bga\"oM\\~4LE!+6}L{'qB3Mp`]f8nW2mR0z^\\X\")lp8*k`;JXtaqFYZ?EVh,xNXO1x!w-:='QAkA;?i`a\\,.3\\F[!WK35T~b{Fx6T1(K~X f>~)2kQ,2=O.O.B.BmqpZ}?3RfU_Vq0bcWtb%4Jgi)]zk_w+Ka+jY![PgQu3UlwRXC]1Y23o}LoHLC^8K#3Zj0oNlYG=#yBY/8rm'!G.Gzw~n%F!~vZ?D1Nt!hn?hbIziL#a~sA[sDC{'Z@5Wa_VGA]{uB!u3@o_Wx\"b7GExfq=pjgFgj+n1`O^mrx:v4N9G4$>|A?/chIe#4wg&mZ}X8==G%_dQ\"]ISWtU=CHcj^GT1@w)x6G _|!0J}Wc4^[0zg49$Jf_bw9V[#ou[nq d M^(pl:lMb?ZE}pqgH{D4Z9-,5b$?=_Jx+$fSK2X(j_ N%C8S6u;Qp~]S8lvVeI|/BQOX,I=q-|OA-c[kuD4,Z=!Lq;`YxkbhY3$LtkMs9I_^}$xcNUws..,K`Bn40J%|%v~0!#f+qomB4F3G*B%8p0~pLa&fULRNXI"; MSGS[33] = "Jt>x[\"E8B0,(K#e3}`Z).obGFt KQ9dV%>l1pjp3%X8||N\\!cR6k3a,0(T }8SZejLB6 5@Pau%8$|eFmv-%Bce@!9;jJCU~B_hqWjAFgn|jdQ-.g)K{~4|S~i&?ZAF$iF$7wW&n'*?AZRg:BG$.$cOL|\\7OII#p&&CYGh}bm84%oiVhyl'fmW.9W{Sbf2'!FzNY|!=Y=!ViX<*3bE=<1cjY_Q~ei8S<&kcG7H>VHw\\@tvv4plyF&t|\\L='AS|CgGa.G\\p21 l=[4Dz0S}}e*RpW#-D2Zv7nMlSrv8zG\\9${Q=M=sPFp\"-'4:SR@1=vmh]4Ati&u4*x^4q%O3sqU<.z04',vaNm!A+n2Rl kA#'#Dy\\))h,rWZ@uyda}e2`!4z(\\qKO C~&?xB&Xm\"4TI4|ZiYK|2qnk$~/jqPgC`z-5%K`-Klz8R kkx)[J%x`C1$HeiUWyS+1'eT44F4QE^W4ibt/P<&,G%IW*BJ*\"\\w<(E~d~b>9K]/bgz\\{_77u4^z0ow([k0;G|S*!^OM[ H[@&.go(IpqMcoQ[wY!=t?NGpW~kj'66/rdD[o:[c|#.Gs/8M{dFvhNTfs~;%$t2hPZ|KW/1`,-HF19}&Q&!QJ+]P=ftU}(hk\"!` {B1nK$dSDi@sF,'?S!j>S3gEBF)OxS/G,IxUm%8/d2M_29jyV,DXu\"?cVv%nHc$U6l_H#H:@wwCP+ YUI[QMB^MwdDRHcEJB}{jf[$EAcT8f;p>o&?Jm2x=twj^psoVPyc}ZA`P-oP!@Zv]xCl0jkzN*qa?*[~`wkoR*JZY~]ubk5-prY0N%0#~704}wj|Kp369pJisPG`-^By6IFlO>hvRLd6ZTGV@f3SYkbO)U)Y8~f{XQ<\".a9/Q'pw]4'VQ[GL{Kle>j,.Iv}s1WCF|1_}2]9>#x8/8 4)a@0-\\n!!xG |tR.l$W5/O!,9kI/0%klh<,UYMym]\\dF*3\\ `E{B;\"6#3a.z\"{)$30A_72EM+\\l};E)masP_-8,t6/w}+o*owADG-5\"jpN!sy!lxt;0bTk/*s&-nOjo[f|_P'q9/D@qyYp${H>]mU%)^[VHhkXf?bfn!0y:>pd9,!?{Go?mLKqE$fjd:4Vby3LrX}9'1{[bzN{t~'m=YSWGrxhKhmZXI'RZ;jL.&\\sBP?Pgnu F9Qe@C1^Ai:V+o_03i?~dBsrT$DBbxiA8iJ7/3W5s!i6Dd|Iwmuq\\-h:md~2~t_T9P7l~lM>CReRP=C&\\LOGyd0{syF\\+f~*>nr&;IR60l1R*%~{o?rCHYIPVhz2e^9f-K;5$$o>qvbjaJz;w~=S-[O5OaE]s%Q|8[\"D##gj'{g&Pb? !lY\\/YWm(9TQu&kwb*[j)8a[~x]K8x\"1i6M2tfr(3bF~fmG,U$ip\\/7D\"~X.!}(gE!Gyp&#$*5n[U-1sCY/27o"; MSGS[34] = "b^b~#T4Ulr8=F-v882sh[RbJFo ZIid+N!Z\",$T[P(\"5)nqVW[!.%VnFz0U^l:jY>3M0He4Hrp3.JOOB*JTevfK*'enLQ&[r>XIc{-ieug;57\"*6I`XF\"ck59~cb2c SSX0/8hRLgD;&w{F=igz2-\\!=uwyv*.-Khb\\~dYhuxvt1/zl|L?M-G{G-sV;!%10`PA;n?XoqAov{}dHI>]_f5]VE!iWr=g:v70CGYb(\"^wYe_\"DqYmaMvA(pqIMEg3F~C3!olM\\^A5E2-]{KM\"n*dZcEa>{x1Tz>hUai~FM>lF{4QUnz(rgumWk3:c9~vKo7/QPsaYcb.wn[RD97Aq[?hGa*nu(CrgID#xl-AY\"nU~(/jxa aS!,2%VFOcx9)nmYjTI3.`dr,W^X/xdg^wV[NVE[o|/_([nK` 4#\"zW,%6I9jH8h4#&RqAtV?|@<(U/=H3a1{-#@xJ>8l4U-Wo3E7DfXAt5XX:QXxdvt*i=>-_y7\\7LckozzuPV@hN7DXlFg[/.S$11|U/YZo9qGU3bc@lQ2>NbS&hl+,lz||Q.0QzoIy`U8F'Sbxv5g3m7\\rNU&wJlL`%U^/LVFizfgG\\}X1\\i/7\\:*e;yFwqN'Q,~|_.Y6C09P>JO?9:d)yO<-wRg*Kez4NcS2Ay-|cADs791;oA>j3Q`bI-$/oy3ptu#Gnf[?X5:nu8G^=ywiNb03|5]Y>aO{),V[wl#W8vPC`YjUXJqwOj6YzX~`KYFI@s9:;lT>=T5FSzIh:%$20YNTnBi\\Ozf\">y@T8n7?R9s^R~T,sxQ9}{``n@:fsD\\xvwKldaLLnwgyLEz'Vsq}}p&q!Wnm~xH\"@i:0e<;VE;n8LrBNI9>>_,.+GA!l\"9U1{1#:2[.#r[J2\\An (XRjs<#Y4rVoB_:4KS(F1ne,{LAu`]Y7]]Pe2B.UGj1\"s%tk8E!BF;lsTc7_rM$R.kb_o]^OtTBx57}1V>q!1IUzk/R+7 a^QgLi:q!C[LBI+47=N[5wpfaGBY_O4L(Z2>OT[W(k]+=(sUB.K|QPb[ sw/V:PJ'&ohpXVYM>5e>}sb@\\r>vM8/ *athrE+a<*0h<>ued4*s8$ax/0Wkr$$ci!-Cp42J(P9.\"dH>Q5%(l`ed%pW?zl2ULA#|&6vD~\"H#-cIf?gf;a.v#./o(23YiE PJH|RNP'\"=1wd=H*LY%V$Q&ZK]|}#K%Y^GvSq^aGNO9Nv3(G]pWzzX?~_p/GJ1wO<^9y_pFqXKRBX_)&hn1/_V-4;|V`fo!'ZI?2BL6}v-t!~^FPO,Wvm\"*:&5Usy&VGS,$S.S,JP|X~C|O(A6Hm8tx:fSKyzqS.6q_D6MO]j%+RX,SFU|\\XH#fq0ZxVH!_\\T\")fSN;1@[easx{}tW$e[E|XPnyne|jGlQD~;:lJgnKZE'?5y:)b`$Cy1#g|'nt![xaO!9NE;j-b6Z6-kTX*/nmPhsS;wbW`3Wghkez~CKH/Qa;q4 x)CO[J5^*)`E}V\\m?yAD_)\"IP}Uq,^:n*Q/:siSZ-h%vM|GOOSOe)=\"d~RP?@=p\"tWJ0&}W:#Q5!gJ.|J&T]y{U.(~5F|pfTIVg-NZI#&=RXp,C?\"X#_!)^tF]hBv3Fj&lnO~~X_GQrf4d)4FKl7\"3q,wyg7E.tUwZ98O7PXCpj[\"{5i8Mdyu/TJ mB#KY\" j{7Z+!]a]{dnu0wZWpJ4l2*.k]I4(yis8f2wn4gvjw@~x=7rgtg>5r|,mknJGT#cS]1YE]}Sf8\\q!)=EQh/NCj4ZFzE9Q26\\Rvs>&@s;2cUbsD_j-I3m,iKy:p7R7As!:`O(zIBygh0dz5$%8M1!_fiX[QqA(g$AcY,ZWTIFT+~&X<_33W}#5Cn\\u!C]7|x GvkJ^k025^,nBqBc!RFm^A'YPCIP`.K\\LTHD{sLj#)B_hfNaY-.wv\\vVuppD7raT=*;&gAiD+y>aJ.=5@5AGnSzJ7a_xw#r2A8b!>X?Ynx@RfD!o3ztb\"@{.\"u-{((P6%\\l'Xt.y8`Mp+BA49UMZ1xz#^+ >xt$\")8z:KDZ*|0kc]|Trm/PX1uu2n\\Q}l4JC,[Ij+2o-by:f-30S(zDunLbxqr2_sjR|Q#)ZU,B=BLnu(?{&?[##O}s>kCo.Xw$-FgcQes;d#0k0P^|yG3]A0L3eYh^cCn_~ySb%n[~*9akpW=Ey*wWMDJ2F%)>SJ:b).dPZ;\"Op@Tq\\/lbtW[^Iqgj3SyK*R8PGTm8|;~oGi:&S FfSk;G'j+LnDpg\"k|N_4s,!72HiPAQ/ B='jn)g!Q%I+ t2,by:Wlx;OB>O(INgfMz8!.9IpP(nCN|vMI}Ln!?JI^#w~E9se]B(.>jRT$I-H[DQdBB~tL,MO/JJb^2e6?8G,!{L~NnDUE0uBz-:^ vq+;$cVSm\"X\\Wf/Vok7}z`5BJF&{qyoa#YYAThQwDe':9NeSE?:-90w6B[0{]5y@?K9N_NuX@uB%2$D,dTZs\\sSdOQk%8[i,,UpvN}wHo2.VMG V{4"; MSGS[36] = "K4IN+,&j8e^K~%[KHJ_3l6oNXyHLg]A)J~yag4NX2';|/]H07-G/IZxj:lr6wB!'{:V#Y_f&R}?oT@.;]!P.m(DpHZJ(Tvs\"(MLu:tPV`ojm(@OO[GYnRev5Esy>S#^>-ht0[.:eSz?TX_8>93&M\"Xv&HKCiU.>+;pl*Sm{8XH#dbR2kjaAKE!KU.M_r+>5ispnMcn|1|Ff!~]H '~4/abiT\\h^mA`\"2>KwX-3P)T& W^jW'SnLUWf?GFsK5_?H!UA|cI\"3GZb[-n&EJo6YdJ`c_}:)e{.('L'@x$m/~Hk~H5wQ%6PQZ+r=[>-SOM@W1Lk/0~+c-M MmA&[ze07-1|SrNSAGnpN4SF(yu~5jH.B^\\l^A=-{AC'.J*~1`y~'8-2[7!?x7@\\C}03p[>ncpS{a*nFXr y#qEx(glS/D]4)\"Z'J\\d\"#RyEe]v\\h0&ckgi6CDMN'n!J\\Bf[!9X2@5^Ic=peJ^M8w-ixyLRLX&UpHM|H9iTdd,*YlwHIv_X)B=e%A~I#-'pL~1=a\"&4Z+sgJf6tQ'J:LLtNY8#[1E+ZZ2jy<|jDWHqHV}hgvr|Rkn.mJSl+-8o'hd%t+#Sb9dE>g7FoFuH]6]X?15.MQQ'Yb]Um!Dp+ehyy)f0R-y%t\"F3K-n~n6CtW\"pVn>Df;bH?\\H@aYfH,QBLO:9CbbRsBRJEBi>gz7eKjN0z5.{#u2-OxKSi>q4*!sOPWlf?jGLJ*1%Qt@BKU{x[RC6Ho?#yr4yl$;z#C$=&IiLTn*p~qsH/6*Okvu\"i(';3q.5M2pc;w3SL=rmnQRrNP\\nK9t!8_If_:&G8J)p%xuF}p72e2a.V%@eNmq&VP9 Brh\"4@6[TfIInZ-y=dWEfLFYb?|w\"Mlwo.hsgQ1>ZffP+R%Gq9WMQ%RF;#gS$#&iq8zabN!:($EAAZd56RUZ.k._H01Z0qOS+OxPj,%>QkOG:\"lb-5LivgJK,tgMgwI)}ODjlJn\"6hT,Eq[}f)hkyGeZ g?x)-=K<0}pv`MrU#YrTf%x&;Dc{@KmG~4n=Uin$,=N\\sG%eML=v dR44{_D_Sz>SjALcpm-%ZV%n$>ZU;:.wh=7b!\";s6FX!?(Hwe6(B)sE%%QSw('u!\\3OaS'n`iJ1:h}$WXDL A)$aZvQ>n]O{$1D'wHu8GDw]JQwi`Th2My5AvM}HKbz3#v-q%gNm.ifd*JR3KDlMND$EC%Z-'bYdd.lH\"23QsIMHI&z7}us_2B6D[C]8WuFx*T^kR1wY40iL4D{8Wb|:,l0ohQ\\%;,ZnA6Xyk4xUK]L^HU-Ug@w4hXZ:v+{sv-rHo?_Pa_5^YFY3hfR2Aw1QX!9jI!ZB!'nJ~r?"; MSGS[37] = ")c=$A6g4$\\[qw+{&d|ClXWT9OY6P:ak3je6ed_BJ'JJC3(s -Pv,k[/BMpMaXzW.&(+#D;HA^B4_'!`*=*^A<9J6Ij.W:T[w%<*Yn/+)Q)oO[7ctz%k/y_@QnAS9DsV)[4g^\";{8^7NjJ.oej%X6A7!>il>+e9rJggUq/MO=PYe_W*eP 9dm1we%m!D~/i._Yo9)c?a\"qE{3h/$1)oe(Pr;W>b'& G;\"H#K!Vl.)\"5!9AK@g,r9#e\"[vao]\\i\\F[!1Z'^e:sJT>2anIUVI`G`\":[8JKR|\"x&cGzM6A'ql(BiD+-h5#a7BRY$-G((L!1o53FP(ZnV;5r{LZ~O67)Rs~G].^,Ux*(gQ3=Og29:Z 3:-E3*G&+R{+Gf^>@Y#>G|p0JC|pXYC`_7G&0m)9k7)ph$i^.xXnlVutKP^79X$'|I;rk3kQM#*p2.*&rGKM.WB=iP,G@fQR!13W+j67SKVC}C F]=&&\"s~$\";pV.BD,~m@EI_`\"P9R7\"8;H=89qLm4'vWd#|c>6]1$\\5D65&WOX/QH)~MT:_omS$mt^^v],nU*n\"w?3D}tncV5Q3rz%. D$[:B+>_6[qV}T+lE1/{D|PZ}\"3y_ddAZ)yOZW~h[$lAkF,B>I< .bn)(zox;9eBMGG-)-!a*Y@SupLbY y1F%hj/O]I'hw?L]*mx>C=h<@mj/] SP0Xu>zupBGi=u s$?rR{eON[_(JR:B-)th=0!3+9]POe9ye>HDp$\"[[v1JkGZ7Z7-QQP\\Y\\v\"G@BXjZ4Y_],MT$>~Mk;q ^qZLmu(LA7FyE=vgmY3Kdthv+=qO[Dl=(x-LH|Nle<@{eE/[0m1(\"FS$h Xk,Z9nb!bd|.o1}:<\"z\"_|F\\h-JzM60m5e9E=q$O`dL*B0#&=t8BZ2Ar{m4!`cy_XBlZZdH~g5|%V$G\\'h/G6;4*,=YV=[1Fv0Kj4Pz&=0!X~rljp\"H[YkgFxgu6G14b(2*pEXAhtx+'~xt?:cP51HhK4KH:&:>69Ld7\\I?VjdWGQ21.\"+qSFSX+/2m]@+p\\Us@`Ib#~uK~.j\"=8jUb!u5,+^QD}{Z3b`)gFnmibCU`L~ S[d!2^v#wz.i|Sl(2N9K3ZOU]~!k<0'nb+U`pDBT(XUM{\"5,7wO$B!d_\"<*vSa82=Q7I&KPbe%54{7}4X:R<=YL%!guFqv\"5_fXuR@JUATI;qt&}ZOXM~%X{T$J)dCzZ(+?9I*eg|1\"uj$W{Fyt1sd4$pL7;!0oSEgW[Mf7b;[U::F4S:iQ~Yx*-9gKZj6\\qi,XtA|\\hE>QO_NgR%8SiWiHW&ns6QtO[&F~J9\"ycmZ)g|SlYPp[G*5N'y7~0kOH1;l&7U.EyNKtqQjjcmwaW|@`5jgD#2$Fx&edq~Bap\"2kaxWyiEd/xpIJ*R_CjSd9+_]`8Zq5zvUNd5Y'o.{K^UQdnfJ/p9r+]e,$j?H3I/:Du;/qa>~O1'o72vxpl^UT^]op%7{Z#m/LHJVj&ZSW\"`qY&G}e@0R6K+Hk5s)^oN9MM0NS,CQ\\:&<~e,GW=f[!>9\"1*IF,UKR_#!M/>1|W#{W(T.ar{vv2cx~l}/0y.aL!Y8BHu[\\Sc&R[3`7DhR[s}{.z73J1X_L`mG!}i!JC-}*$?Uh\\o$lc-Q;..E>vjcQ$U$Ug>1apkbDA:R+t!3(In_,_yG:^<3ms{CLU}p,ahvDTrx>}q2KU[vNQ2OLa.X={l;muKRPw9U[L4`j@+(W)&F8|d@eKsbmZ^fSL.>q U)yh>Hml-+^2m> tk>#%+Hx[=C1I!se=5C8yn^R?Tan%:OioF0K^'+_>-[J_&pTXH&3BrZAK#1j2#yv c\"[ JVx`l6LBwk3ltp.NaFOJppOX^GFZ]$6cSTI*Nt6.m7.ES\\Y{QR|LG}#/gm!34c%65=)6yU)Qy{<;oVdS}<:w)gpT)>~$0*,wg5@PRBKR}D;[gRLD )]mJ[G[_oKkE\\g4t JzzOh[:?!kYUz*,$R,n%8G?n#uf1 e'+pqkHt|?^mZT]^nC;Y:eQ>[*)4c,t)!@We@\\SF7|JKM>C>nh%,,1^MC0go]+5YGh&0xee;Gc@UaojxEJGD'<&2JV=cn\"\"hcT.#^oW5b}&P-vEi4ft2*B`{8h}>_dK~,+T=|Q\\~WV}-YkjH/=@NIHrkPQ2Y0wa<`UJra9DtW:EvF{lOVd?}#.d;{CyXd}H{&e3U3-f2osVGSF5I{M\"Q*P1:5#^q]e02uF1nY{Dxx\\I5M8^W{s#/CzSDHW#$ T~zroC+!.2mUVL|BvIln&W|Y)q9g`#~9(D@+A+*h|sBO6V|v\\6ma)/Rz|3LzP\\6WF,6\"@t%kLK$=M\\iy?TI~4|<\\%Q_$Z+&LRVHL7C/XYTN&Z=O!|pr*~TaR%.6sr,<'#O_L,-%14\"AZGH,Cpj.8aU])$B;$u8hi\\YRF7`j$#&WtTJ]y_/PNmCT^nbbQdYZ|3c\"/iX'6Pt4@ N.l-@WuG:X@- R0S2tP>P~9/0spLX~.Xi'j#Z_[+bIlW&oQOr1|q6/L:uq2W@dMpD01Jm;r0Cv1}.PN1UJ;LTJbY;`!Hx\\$jwGUTQ5T:y(twU<:P8*b`.v!,PWmid.vGs[&GJO;!^c,iCdtA;a{\\i^G'=:x4ycOw{\"1e ,ci!o8 `::sHFeN@(-3;v~zZJi0h.z=|4g+zFAWLw]P0u8lp9.QUUFeY._v`b}'Tr\":R*OM4yMie\\^#OL &yoBJz$J?$zru8s@F[,>|d!ipadAcSf&t8.getfb6S4H*Y\\,kr@3O{Hgtp1$v2)|'L'e)h8ta$WCZI\\(qP*z27#5-sgw?N410;Ee$ctr{n\"[\\R(4kQ\\%X"; MSGS[40] = "?ly XD'<`Z9w/uq/4)3T&XJNCMZ.Vn+ckMnTFB4 actf=p$=qP!w\\l5PnTr(uB{pf7s.A|*%)?VS(JuZFo.t^$[7VR`~9=LS>}:,QXTKw_,VpSF?zaSj;d)0[=]_E!s^}cN7[H)5,VEr,y(*$Z!uFrGMzdoGkoIfm/H.Q;Ch4?Ff~y|pv4F7Ba=5i.~1G{ozCQ;?MBau1\\*0WzZ`}IJU}C\"P%q2-jMY?maqlyiOG~\"w!BZcltdZ*+WUuAU-h_d~RiQ=&Ghy\"65!o t4_wj,zya0u[p|0mYED?yVv!ANk-;D=X?k8-@;QcKHqiE?7}2o-6+O?(S)1\\LP}l zjWGJ!e? a^~@L\"E.RaSM$N[XaL a`~T2M^'dQ\\mcy.-hL+v0tn2X|YFm%[WOi@}/0@waQ;663vmN7kCQmC7mDo/({BN`}mz4ktR(I3zFjpr1Gl|?!nl7[Aw53Pk/OYL'JPVqY{Z)^P\\s.[McJR_sRn^/\"QCwuaNe6q&\\!!`_Z;6$z{7T%b)HT&\\H\\9PhH~O*B=kvV'PS#0lt8J7sgvbPZfq{;6kuDk{C{\"I6,Bb|HxeARM6ubTwR#!vXvmu4br\\S#;}I'jt>#A`o%sX' maqD)A~:@FTrW%Q`?tv}f>MTe,?U0l0;&N@!HgJXw'714f|fz[q8`Kq>5=\"\"9acMn^rU}3+\\*;cm[IG(Q{T}v}kRGcm}Y3btZ?J/)5)LBM2V05:e$vMcI\"At_w#Nbyb(w9>NJc5M,>\\NMR\"}M/oQvn]Hc6U4jYbO4oVR]u'BHw&CnZLOg3;,1sqv{?h`Ka;\"F`T5LooYfEV#Ua)Q:5pOt_XdJ@wgcWn&o+Xrs\\eiTG1pM.Erzv,6}$NsQlHPs0`:C*{\"x-E2op+E'M3~&&jd3Z\\1q45NcLK\"r8hq>%gilxfv)ea=Xo\"c~Bshb&*w9?')7Y8!U4Z[zD[Pv4RlIC`*3u)55#R5u8zAFB>|j}&MXk9@tpY^5K4+s>z>Gq9No~0i5,6/A4#Ku!R$q1|a0Dao^ETYf^}W_haW^;\"Y]bEYmPbZ8<)cI\"yT,<-9H_LYitm&P|ux:,Xy6k-oc{=Y&7A>26,'jAo\\'mI)/u@W[F^7Zj;1*N7w)L~E{4r)>W{/TCE|Q>byn8m02s(>%PL,D90DSu7!0+4R09,~%lo;~j'te,l#,{PR5\\tQUdASaE'cZ9UD9Bodp5dcbY$wu;f(uSkgeTS]f :F?\\Z]3oJitQfUbe\"~(97gQFp-oaeNh-ooh) NKVJBQ[fl=[;gI>Of@NFSUbE,\\4CT/ZeMu?32Kq@[vl4KZ/3t[\\\\3Mp?8kx0i]i3>+!cIOGM17Euw!vWF.q}!+g4>SP N?Y}q*hxB}J@2P-5,?p9>kJ>]/~(;UO"; MSGS[41] = "[dZG)rwbF:iC0$2k:uUkw,{Om*F%2E=DggA8]FlL5|#k|Y[=wW\"9dzO}5w6$VI3,=4v|~jN&bF(O!L){p9v1hYD^Y?a-=8o>:K3m9|EJDD>CqWQ^R^B%Y2:A!QT')W2P86%U|,jX/<-gQ@#yx Q.?\\|}Nu+f+-=%sb,[J~O6uupUBz,h(Uw;(mZ\"$qZyvrQxiqt4.sG>I,:fcR4Oybd^a=mu]^ARc),4i8*wDMjFXwK`1f/=*;*ft]^A=u\\Ppn]F;f#G]zKLYK8O;)hlt-k)/2zY@{iaNb[86+4Rg)FVcs}rN46sESJB)gG7hXuP&$%a|XA'~sO'ek**QI^\\!?^ObsYBXpf3*p\"EKz 3te0.5opR[H,KPUXs3)oX~EiB9KNn'Zt86G,h; Y57'g%8]pE+>ud=d3KMr;%,TNOQ6U(Jj# Hc()7)eEx#5SJsLRgr*T!>9a2'`@sJXkk(E0#abPQ`jdyd}N?y0w^ [L3bi68y>H#PkZ4K3o&^D F7[aAR2r4meIEBuxuL[n~X7B71uJv^!RwH-19,hvE|\\/%;=jW&fRdV :'$Nr>c\"/.3-rW,TJMZeGM/!u2>|=q72P*n_E9:,R)hGj:**dX:5Hj%@!]dccD\"?a8W@s@MWb^woRH}LN9Jx2u(%OYsxL\\t1RJp:gtr$e$jg^\\!W8#K[h\\!0AoybdP>(xb0`=>YBd,~4gpQ%1;Qcj.~NIz#>U!Qp6;>,A=o3~=4A-V=.[D~?qoK4/oqI%'@w+moQ0VlOOWiM,t%1-uws;\\:tq\\>fUFH=V? -i1'fY)ul;`2fB a\"ETtLM?;g[(>kT>K:Lg@C#u5X~Tt]8@xr@yl+iyCs=t]f[U%GetMQt|Mo~/V]6Xi%v^~V9~zyo47:I2:5Hg:-EcgXM1;fZn}X.+^=5.(|d'Rx+C=,1k*]3m~g~e M}Rin1='y[d[#QYB$K3+QDSX_b,fKd'>cr2<8:NQeT3VFl/RMnIFSEJT/)UCx7rH+MYP$;vRfd9wUiY3,kf'0p|)@2LW]cRSznu8`F?]4a{--x0;b]:d,]DjMH<\"P!eO>{L\"={K-M7qzvka[+{gqI& R5(k`rZT|`~hXShvv6&0ecXhB;48Z)d?~FQ)D$aT\"@ZnjYBJKoDC!ey)>=^X)2H3S3YKTatGo1uWgq`{laFG(@A8Iybr+F^-w2h<'#V&DXwtUl2+T2A $t*}2^^&/J;'OkcS#LA=OL_MT)%dc&iDBXOTnQH>\\R-}!2g\\)TI\"-#yF\"9]taP,x46qv\\&y:F\"@BVk}z6t0%~5Hgj,&e&k_yy-} L@WZ;a^n+tn[p)aB*{y8mlrHPAmZgj8E LHq.S>;]X|Qn41nr}2$k/ \"mm6P)*m}|wpH]d3=ct'&y[w+mk%dX?UbU\"L6[MQ#2<~IsN/30.mTfbZI_pN`(sm}"; MSGS[42] = "3FQjuzcay/TCNMI/k4V#1cFrk?<'IephJhM5Z}ka[KW2NeHoNx^e^ldP3kt&`i&F\":$* 5*Co <]7TBpyX}xF'qeQX/sz3Q'gK'h>#Z5HpvhqEQnp~q~d%/T3Y)EGBO6kOTFI1$oZ]@MVaN(_ym0WQW^^YU#+b:j#`:?'a!PypQ`At(\\_r5LA[YDyr=0YN@r(=mQhQ!1Q[\\X?2C7!:CjS1xR@@lW&T~:aGvNB46sL5L'hh~kRS7U._noP\\^^^4G2,HQ&.[8MfpWT`Gd3s@rm/}A]rN69D_cG~#p&H[G+|Rj6iYq,nqMbJ'FZ8R=:,::Rm=/15BW^)>;IFiMe$B$;H.3rhQA` \"{Ex_;@3t60sa--:JZTfJ'&*RV \\\\p]_#;ti3H87auW`=0pFN=4R(qvI[|kqc\"kGT-k/BadwU[#_C|=fb8L=uphM/oq-|w;0`E;OG&DS2%!Rw3E-tVE>:Y32OS`@aU5LL)~Zh[on-Bb9+Y$?2\"B#N-QV>Ia*(W[te$TgV%&%07A4jCp&E52Qg0Uz:t8#|DT0/_-Mq~ #T~s= ui&Fqa{pJ0v#_EsewXmLO'IPi=|@g)+FK#8=u`k!&i#qW.}D3}oeJ0F@T=N1B[8rNlhd^^>8={cK~n5!FG..[4n0vj%+V(1R4Tj#G]C}g3BQ#pk,_&]FtE +8ebcsd?Dg&D4_Y>&vWHebWA`b2Xj--O'M_@^|ufCizn(Jr8 o>~2PQ%R}w_Q%Z5dOuT;FNo]S4uS4@Z`N|4Q:V$)mlsk`l G9SU^:9n`E##-2]e&%v>7;yM/#C7dZ?ZKH-t[vI-Ow\\9J{}uq#D=#TOQmCL*+bY7iBYBSOtfR(Hn)Z,_a*A>\"b>MnTp~`%q6QXu5\\6f$DZ|>Y`>h#-c9{u$ W-9Y\"KjR-#OQ95*=k!E~P`h!Uba0'.wxz@ a v/A3l6AA'-u#96eV*:?GP>9u=Pk6J+xuyoS`3>*&51yd2(X?W=!t[duH|k'GybH|pX!-O\"?)'ruo)--GFo6R|p&m;Uqh%;rjdv\"ZZiQdDl'$MN ,YQ&E^Ut>g>c<-rxRHkW'I%R'O 1JHQ;[ub]#b2;?GHqyTOKv9am[7Rx2.H~|h\"I&{\"x|hU8R>}/@=u6aEbr:}04NAP}OJ`1f LxJNtU\\cJhbB)T5H,aS`;v?-vCp5}/,q s@_gU&?,5C?P1jj?+rPgA3 LPNA\\9I96'XjEw`HP-sP_QS2o]{\"$d?^[Qn^&0!]FQQGNy%[&fP'N2 W1IVO),.a6)({%I'{JWx/?TkH7w}t8h@e{`l%u<}03@=HM0;Qu/p7ZaNjAl-DU/O7ap1{M,2m&t]gcBUX_B2]Aa;;bL-)l])?Z3[5?2H*e\\0IGyY05=\"vtSp<>W}M}d{6PhA>|W5t/0_PLdb K#S!{D!\",-k;YcjYR5fW[l'}k\\tT8@fO&HM1&Jn]0D/ZM7}[Yy8(#2}GaYV_fLo<(.EmFo0R@>jp5f&P+w&}.#ncx<[`#N>GEu+-!>-k\"O+1='4J'`5%?sgrF)?7T%Gw.clATZY*Kk#jlkjyc? }Jy0N\\7<:QgjPwEc'i>PPK mbx)CV&v#,=t\\8oty\\RJxe)~8 Ik&F'I4p*aG+{,*EMS|]q'WAU:I'qEa9D@[KdvhsO#a?/+nxoZ>!HPw$<[AQqO_xNEBo${6uD-`[#ET[/ yLkj&8) e$F5d)CC\"$|*PLq|cJ[%H\\\"tGUSP92bzcuGL?MOlua'#8.$Tn(#b4i;*wZ&`9b6jh]EvYr'o!Y2ZZdPT4,vgq}m=P+N^QoH>yg8H4yrJo`9OGgsQo9x@u1a>/b:Mo.vZ%)ve|8 KEg@.-_\"\"gWU*Lc(orb `Kd@|%FMAeqk3C65ne~\\dg3+o+jz1-;H],F\"Y8qC!XrDB0!E>{ +uy}_5Fw~pu-l67<8~hHP@4dxkYV89Nd@:PyxJ*^8&I~^3dAR`k1rhtS_PwFSlV7pc-s|XS8E[pb,W$P=QOK#~ vz3EisW|jH}~v=q.++-X#pk-r~PPGfBvsdOW\\,.A$3BM #>@z$9bW$T+nNd5!CLm.^xA47$0p2E+R@l{1DZJfJV!ua3ig6Cz$xuL->En@6t.&[)!m&`1LD5\\u.BJ81LI[zZUehF8, 6hMECe_t?Q\"\"^B`)/)X5b5>#l$dL+i>{eeA%2dyif/Fk>d66qT.t\\\\2`B&zyCTn|Ey/.`L3sEv$^F+]x[F@FZE+k\\qa)P^(IkGmUFuM.-`ytFJS=-n?n{u/a >]6J`YAW!1vvg3zW}UMh"; MSGS[44] = "OyIvr;VoIuA2%YhecyR5WK|EM3}bS8WVq~2rsLFf>/y_}f\\i)C#L'mO-K}(|{BT'IIl84h%; \"z^%y~67ZTv;XT_tcO6GW(\",g9 _TsFPYCzJ;.,$VC%Eg1*oi_1O9;c^J^3#i]x4kkg}G{q#sQW*o$AHAaVO,4,vF6x5Hz:Pc>C3L0UIWF`UzvC5P;Zm`=`xGEHAX6pg}uI|\\gh_}I!\\)UKO;ftnx/LU&5D&i\\N&J{q[)&GRK.OyW>MCSzwt|A}14YER^W[qAj zE_H!]i~H$b+sU>oi!\"}m7l|uW)(8Xb3^3*[2iU^D\" o>'+'>-T,{HSq]!~Mlb{>Bx1DZ0d=FaH6TL9NleARx7VjLeJ7&:?hkZbk>S H&nE'O9IbA]}R1.O]CFal2V>B7r98w~V\"v+8i#V}La;ljYqmk%Y`Jt>~@LP3QwaS/s)n{Z&ODLS,zY$,lq?JB.L>G*u(B>oLEH!7nC5 B5%;w!Dx(36}\"y>W$Q,&-1Kt+Wu+mu'ZZmZZXAK%Kl3xC\\E`T>GPWVEAEs?Pxq*&,x#\"a[vd-f7!gl\\%z4MJ]&\\8v^+^H jI5I!p/ieq}&x!JIU$:&gS=-C`/ch\"x(k,xQVyfQ,4p7V[5BCIYm]>b+6]NW}&+BHx?g9.\"llhRI4x0K9Hsc}W.@-H':rvr\\>ygy7-d{>hd1\\M^\"mA(C1h8[AE8N10f=Q:}muMI}k2C8p8XW7'PIY@H}6cO43Q!`h*+lG#RqPq@q<-q5~Y,jlR}i:zcxq>813Qa3vuO(5q*lM?'5&A*/pXhmU)D@4318;+0pH6eplc00].?3b;cxQ|SE_kl9?T2l.q4pgzRk/k@)CpDbw3phfVli8lJO_v+E*-e{e6C6/UJuVmyz=YKP_$BaLr-bNQd'Wmq>Ucdvr|K'Tj1DUXI<$67mQYG%&MLn:N),\\f#P\"fU%{QHFO_#ORePM8pu6}5c|_|s;M>'@Elvn0D8TdDC{n8>o,>Z$h`YYuhVqquqylP=l`;P\"XpzC~L 6o3O:0K6Yrfs=DR,qgNp%kr]CM|_~;QXa-B&i>>@1p,DSX:zpBdOXlu5h8zWmR|0B_`T0$..l|*EYd>R-HJ;i=~0tk98\\w8\\32t-jB+U<%EcZN`J{]V{JI9Bv?,_gf=fZ(?3,Wa=9]0\"UlzN!}G_F^2w9]]iOcqsc*Vhad8Y{K('7?zA%q|u>~}QY`Jdl,F|\"]T*I-5k1c[cy9u&qYdJ0\"VK^GD)/)}*:f,9V,tfA*^~VF^pXpk8Q*lpVj\"*'s,}y\"7IPT^nq_.0uysM0;gN{9TwiEO[NCW~kOxc`<<0!^OQ_kB$$=0)`\"kv#XGCuj|I7?f-4j+(L`=~X:oMwy=A\\)#d?z([PCN#N#Lwtw)Ol(jt;}vH:boLh='56PrdyQ|xux9~A=W2CS1DOirEx#=;,}\\(-(dAHi;~txg.t*t6ZUqXR%o/w_*QgjaU1Bqs+q=ZRgVEy)BQi\\y.969%pt&qy2Q`)#H^p^27<:Bv3i8!6)^ _[dz7m=rZ`#c;&X@@Y?XN;`^z#mi/h4:o|Yj_laK\\C5zmE]vjf` IuCb&nH&E`n#CJ/[#l;OcUbOV*&u}uDQ'7M?wo&~S{>}SbAnr/j;cd_#mN}p(s2a^\\VyQ&X@hMHHUavNApXBiS W9.;xEU[3F)M@I~I$b^_1RrOT{~E[\"(zD?xZi4ESeq9^Yo'CnHpFFi;,:Y;e^RQ\")jh6-wSEf2Cv<%5G>/lWP/~o&2{Y!G+G+'+@MrC4y;W6q]iw(RSS,vx\\o%Fe1%@5F>+z=5s?hM@N.qqVc\")1VnD0]P#;Uve91/|8?Ursv|d-I9fx7CFxq;'ua?;M>I.0 GZA`x$Atly1EXe}M{N8QMrkd}y\"Fc_)iN44c3xjgfWWI3k((Q8$j?yoF)oy,'F{8]3:sKJxT`,h:Eou`Y_<[`\\wEUJ*GNOpE1/A@lR-4j:Kh)o`{>xt,1aF;c?t@yp4&)npLKM223J|eEMiG!aSZeE;AC7((BrEu#HU2s&oBg1FPZWCK%|qR%txu!yGY,>Q-N)i=oe&bY/N=eatF[Kl'$C6a>UX+*#3k$6lAb#8>j5*\"0g_3+]Ia|#;G^z`zi3C/G/|9qgW=s\\ltn|.@D']6(%l// v$dmt P3B0vn-@I(qH/{lN<%pK?R%+wHGXEN8?T(`6NuGn.`9{'@V?E;*E:)rf\\Ml7I&Ylvh\\~bI(VMCg*u=\"H EYX^3 *1$^HG5tA#cxWQg\"W$1{c#fi\\3&]<}}hAmuSbv/c,#Iw&(@X}nCq+[d$#fC:}^%u#Vn[%TN5qqf1gvN*0og|Gk=*$Q,1+aYxtwh~`gJ1EeCxV2z`Lv[!ZFi$$ho;57[XMvsx`mNvNrD1L:B58wpIVk$[,O)O>z>STW#&t{^A?dKhsuWG_eG?xK4mRm%EAr;)\"9hL|[3QV.Do.EldOf&;wIW9qW=0D%OC_TzPe^pP$;-Lz.qt%:WL5_aW=UM1N;RPmD%i9yF~t6#pz]l1hHuj=)o;_EVvB{l+0,b[b\\'[WY!5/n\"c#e,?>gYs\"W'X'70}\"<$ ^+)R1dKYW7hMnD/`*ZjGUoR6#L3m_Q]_5RzgPj;Dp8kZE:Pf}:M,{}v07_6Al+ojnd#-YbqJk6\\JuV78U^QgqGi/v^abPi_~G,pt#af=$a%Uty`q.<$ip/zxAkTO-4Gc_paEYzRmcB.^{Yv#_mJE`1qB{Wm{UNg~Lpm'qZSh8HCa5uv5aw;G pp&"; MSGS[46] = "k}5DWR>ZS1,Hs~J+vJIPfQ 6-Oxv0/hK+?zGX>sg|J@n\"Ht6e\\,y'`>V0HwW]=SKC7V(G91fC*_wtdvJ/`uFQD{#eL}@UyFXOy2NK70Te8wK5mFzx#Iab,-M0K~2cwTi9V:3v]|EX62u-pUrw[#U\\MxU\\4I>p_n9@-(,'X~4w[A xkKGurFxsU\"(kN}){NMh4.:(MSn 5TmGdWE'#RB/}Irm(k];ULXsPJ l5tvr-wIR/Uo5L!^Nom)blbxYM|eqgNx?pkO+fP/{G{j#85v6Nf](dFwHyre:i>qq~hNTdqNFz(pADI:mZH3kG_j:EcA?%V0xBLR5!GsW{|/@e9vGt2mIZ#ZM(\"N&h&VtaM{CA.]v4>,rr+^{NNNRym<nWXtw{vW{o_~FVBKAvbKbSCK-d\\mDS:z,5e![\"45s*dPt^}&^eOi`Th{XcHbH>Ex;kM'w#{D11 o^/zX\"'P/yMce?$ bz)-wU.@}-/e%$X}T5(-v0(#)c2b;4\\:,1DEffL''8UlFlBu2cqBM^NGp\"+0!dZH;9:V-='k\\&[z@l5p>al3jR|0li7F<78)y>XcXJaH^cm(#5>PBHAYB}MyY:iW/*NbxjwK^KS~aMwgv6{A(=E/H1_%aas{6Y1-H[0AB=V_*87T:iVM=JC#qkZN%nt1Ho%y6\\&o1\\2:G;dLc,R!XwI$tc'W}~d_M>\\V]xrHrXJxm8?+!qw'@yK!+X$UR0]4HcX*H7LwrE&r(yGcrRHFNV\"<;T`>50@i2x.ePfYq]\"A-T[|t-n.y,!\\8@IR^mw1TwL,^aoTns\\_)g5 G6%kpihGpcGzyP \"MKQ8L2ZV}*HjS8ovyK?Jm%W{>DU[!Zqp?Q_2=/i7JmoP-@0cqvy#!u0,Yt=itq`I%8IK'HTh+Ex^_[mL6]tk+ \"0NZwNAx5\\]U=*5!CFZhWtJ^GV~e>;8,Lyi{55Uy1-%E#|EJ##mJgm?$[MFsz+N?8-PU+NR*^!=jp};$Pv,I6g+ads>`-eP|^ikA.0&l-gMy\"\"SbRX+\\f`%E|n}o\"&9Y^}o/Hk?>E=l/),sl0k2yPv)v[7?]Xd#:M6X60=#6lZAq5S%mMPyWvaG8{k}h56y dz!8wl^U\\%yk-0N.I-C*Q&UV,7k2&3MG57r'|!(2mAY/@'>&ObeU>j$1-EIieE{a'.tBNN<9ZXWed.*(p&P9Ih@-b:6utXaz*5iD(b>\"hEFJ]$76#Pc%VHQ||*sFJJ}KDFU2\"oP>RNjG7su@>*OaF*44IEk'>/:LK1Gub2(\\;4OW@cR(\\8!(^<$[Fd&!nFd(Y79}nxMz$U1zTQ&_oX[bjEqRwq8mcI\"SX>k -_c!:.*Fmp[Q'BIDfbky$Q^\\ uoQULvHHv+Ho^V!H9#!zeuk1H]Ea??r,!(yO]uL8>} @:gwE/ZL0=.'b`| zXly%s;jh^/M4J%?OGrh~^rHsK~2YM2}]#AJnUUG486(Mt>;]iid3[_oE9tBNzkJT`-fm9Td;&^s*40jZL\",ff}McohGk3MY}KgZW1>-{24-ay_Xq=COM3Bo6X4vw]*?rsiAIGh6:faRZw|;=U[92jpilZ\"Iy#z7)kPBSa=,%=APel7@8dr~fla83)+gZ_bqjx}Qi/.^0 d)(Lj?gke5k{*=x;)+B)g{!bw56QM7YR~%'%drTlzd&:S^5Ki\"WU-.zvcZek>BjX^q,\"4iRAbr@-AmQl=XdY?XI,\\x\\Za mP=`L,];~@-HK]Pph\\yuDIFtu,>8(~W6\\1@qNR@,=URO`,_k$L3.;V{;AdKCe?sSQ/Iwr6Dd%{jb=(>a~s+DNtNSIc;A'$O-)joD@#.~G/ O"; MSGS[47] = "}z`y!Bc+m_%c!lk/ageD*_xT+@/aD/wX*1NAW\\dFhS$b}}V2$IN?a`{RE@98jBnVUVXdl'=AgVE:#++~LhziGeon!c]7'7USd47]T,Bb[iR$!&EAs^$G4@r^m@nP&TC$uSn?rNJ'9\\}BoKiaV_WX`']VQQ=;G-Bu#csFn_o-k!9\"= Aois/e#R+*DF SL[c\\#1op&pv,@XucoPx#3{Vog$\\Wx@)_7T.v\\Z\"oky9]`P1OL5f3Y_&r`t9f2:QE[9@?}YfV46eV~gcna{P\"7sI>mb:lB7|5U.($ll4+CvzliT_u'R! R!4nc$,j~WL/0#&:ECuVb 1Z>GzW5m['xQD58Woy66f$$yBlqS_\"J]$/P.&mKrNds3:Qw(H${oRzqK6r}z;D@\\[M\"8sef`BH0EFNblIZ^d;thaplm0,;.IB}jgxt&nJY\"\\$qmTcn#!-LHX=,Dw:r,ZaB20U60](P_==Q:OJ!0^eyMeEH]HT|^>~mzq8\"OH&mGekG)Q=\"pp^,_lsBsP9qWY50ph1ec zUB O2w~q1tw]M+>^#1$tmJG%>:)~&P`b38jdlP0%);7!b8*!=oSy~_^)<%\"c[n_{xCSR#M'rG{qFd}8KkK9GqH7A_vsDc4[,*tY%xq6nGJqo'GDt#/FD)KfA`$U;N+<70AX`Gh5{yKTkBf[UIb2XC2_\")Mp,6)?vn OMA9GT_R/\\ZA6wWOg9v3B{i2RMb Ni&*V[Wq5@P;n/zvz!J'GWw{|ct+Y's>1eDJH7F5i&8?~@#`c';\\u~q/DCi?HS}-$M(XgS*=Siiv0rT'w:=e'&ml\\/Rkzf_JxnB&Ea>u7sE]oM*J9znwPgkDkF(W79FSVRNAk51)JN]$-'auD+!\\ruO]'04UDLc:qkT wQa//X4B5AnH12 <_];Px}nUg>Eu=t1Y>yh>qAT}]Hd(&1@dK#Yyl,@B_H_9 RKPU$:bW4b4r)=,N^mzBcw&|Da=_KF1[R!45'QEc<#f9Nc6s'=[Ap$2U}ux5rN=!WF}mZk $=kZx7a:Ltv:jPbHtL5auT4C5Zw]e lkJ3LY.E6Jubh8O:W]\"hZH1>Kv\"J; bD8e-]Jn9GmpmV}s9>@cuA}16nBn9~MXcEAEJ: WE&cYXO{iTZ9%P&Ai3ndGxTcYn/+JDov;$H\"7l9%Isrk]h]GXSXn{w8`6YYdoF}m3~j3ZS2A Hg#o;W!?,RMD*;s[6G^H88|M\"T+6/#$@wlofAl$GtNv[?~pDDy&/2C@xF_Jql7W){pz]sJAk:p6CWE)j-FaV}r9{k^}g%9Xj^1d}[C%((!ap\"[2!FRfC3~7BI+e;^z( \\)(7,F5=j||'$5pm'O/6Aco(&y@w){'H+Sf-A9F s{Hw}]ttQ|B8#oVz=02&X"; MSGS[48] = "JJF~)DIXj,9t**kwJ vA[\\Zfi>nUW(-Lyu/KsI?M&TtffH$K0j=W?02qAh= [Q`,|sjt[j2pUQQ}8XoU/9#4kH8AsmE%4EJ.GjAEbW_{$XCXDAw~P}hveKNPI5j`v\\zrHUS^0HkC\"3Khb\\9k?v#uO)ANRJn['O(XIm~\\jj[\\^P0#'`dme'g=(gSAozyLX94D79DCJV]k`LnT#pSqBj;4u1}*GF2+oYGT.Kc;*,u*jy(nfP=M2;)hcek0j,9kO2#E\"tB='K5S6es+cek9\"v}#U.EK'==6v}cRbFwwg]S`n)>goiKVItrAEAuRP|81{+9x<`oX.8j7m_`\\+XtEGs9QhutRY+g|HCZ7XgyQ> E5nLkp'%B}UfnN_){>[`h~VE?c|@}YMpHfY%j~hL14{`[\\mC\\]G&]HpCY:GM9@*9wzWc.@h!tA-S ytvq:tcT]|2V&<{jj:>6_Y0<(f5M8l%b,M2jY?GW,6>_\\1:MD)5)_(#s9t=48vi\\LnXxo8DlB'o~w}pCzN_ZAH=I9zM)A^yjC/o}w%V0$,W*5ANsm1FU2u.*BL'NZzbA6A(Jg)LAkeEFmwR w+sS1G(JQOlE`nLppF0BahhH-l)vw_U0.G|paD4r&Q,^PVXSah: dK|UOllQ*[e~gbe2m%n/JK98yN\"8$.Q)\\jv$?]w.@->'3LZ&zhu2ig&}Z8**]:SqB6<%Um3TbD6SyVsW;l{rDk82RS+0omu8dK>?aAbSF8QH)O!LlxHTlAV_B=tEfaR^REbwS-U:|)+D*s2H]!$[l*`j`Y<7'h10?J.{Y0y\\:\"Lw&_/|l@9fvk/!2y!Ez0$[b$Kb&2[|nT5~u!Gn&h0y6viQo, 7rQVOk?$G]8%;Ev4HiZ'QF@z>ne#bFoxrZ;yf@YL\\s'/zc=@4r0\\I# m[u-k VQ?g\\%-*Y.R3fL XRov^N0D ^X`L]&Dr:y&&*{_,';:=qh[U#'[g=Y<^KR!YI^BD\\K88[-v1A^G^,;]QmEx)[Y{m(M.;=g$P$<7^cW8 !J=W\\Z.Rqv=$.PHZ(v18%VS~.6=}M}VsophPohD0{T:bUe1]mEf9wvm@lf5mIy@DQ+9vUd./y[y$[U,k$Y+T>;H[]0?XDq7TuhdYvJ9\\/-*Pe'*!EmNJt5&5]2gv?|j*0v{H\\:&NsyHl!Ew;a\\p4T\\\\)^~atTC3[zx\\24Ou={LY::jc3<'l!4&GYUce(cz.m0'\"j%\"z9)n-uM.}L4%nGG2*jDqeh6Bdc=Ihd7b\\ O)UV[4#<0QS]7E}I4)VBCyWs3s\"1/Sp19X\\94FSM+G7!s*3E$<.:yM7w-6B@W>/ 7?WuZ~sgrOA^sz#f!wk\\Oc3-fN@&y%OV-aG\"JIAq:g]0qQvAW5tt3V=:F]\\fL=_8Pk|kZ?:wa $9Y~aYZVX{.YX^8W{)!yLW4;4]v\\R#bHQK~mANq.SlCyHCyMqT~I_L@p_lmydWj*srwWb;clgjD<\"??jH\\w&?E_\\$`xoByp!jr`.9g)8[X2.nOB_^3x!%JdX(#{1dxQ7s0(25 N4Z^B3~q(1eesbu z|Lh?#iDC[\\^meu$r;{-}~GM\"lRq@4t#yN3cH5KQJ(Pb>@ak':uc,~ reH12I<$R=VVp0ARRFUFy#iQ7M hG,[9_mGGzDKr[|E&tDshC@Sa*XP\"+h:R#\"Y:BwN'.^Rav{pGgO50=J=^p6/Q.G-RX/*OyHg}/55 v6^6_t%g{;F$w$&usWOff^n=*lh-'FU4=Uf 7@3z>NE\"kb:\"_9cQq>.SpUGXXG fmK7*uMJs< dO`V%wtNL$9&5/a?@p54cr-vw!9$#\\1):jD.3^6VtX'0n6a!]~Rf6}{ky8suPK4+gVLGA.KhnY.c%pmxY'~o~>xTCA|jR_M0uC|AEX,L=$!l6E%h[Pj3eII9olK,0eD&X%o)ylmE7,TB0s2fui>2Mt]([&#B_&5n]ydYO6=~<,\\@p8u_elWeLh5*[Bd*Ac:|Y,H,-m?Su;naV@|)0y,q[LFO.S|ZM).;-8nG[T!9YBj\\FBO:VK7^)5Q~hx`.wSxw_9jwXC^]27KyFje*\\pN1/q&bndZi$xN7E7niDW,g{o|GK;6&2'y)=-]}8aL~zHp%r8x *.~Rz9De}XtKtt(:xonu]b`Ty{=A.H`M]Fr?C}e&{AetfNc'Mnij{3pe*o6$^V3d'1:/J&uymBpYf ZEM3=jzo|UAl*EqryhXv3xx]6%aH_$qrd3%}7TbZEp!iX_|$YUgBy(M]oGA/U}3X.nWaSfvlFXo2jL_LKighc:!$I]kaj]HpH}|w4 X w08MR%F\"$QU3p(Q~qU.\\3ajPbWjUj ~Su~O:MgY0e4icZDG>P@* *5f-.ZlWL'O3td4i>oo=lOb=\"-KHD2#K]ZcEWLu0H#.1U1$?'w-SDav^4\\ hQ^,~L-@Acl%%4=>QBo*;?DG -R;q';eu'wBj t_(`PA[!Cx-osVR/}d`;.$)0S4=xp5n\\[S913T&ncK?PEhQEw=UiT=](&]-JyGL-OXA-0sYw!f^^00Mh| b2*o%b{=JO^JRe'}o#{&q>D9 f\\c4G3Y\"Z%VG+rloq_Oc]$;'wz.VwWXs(oCao&Oc[F`N\"bE!g_;K$F{A|2:eV:cA&H|&lEhHol\\q7hZY#fyau^^x_1d)-3NPqll)+v&$zP[[[Y'8mS|UO'x>M@7AJb1CU>(#2uiJ^eyVdR]f:A|&Cv{%UbIt=Gt[_)P6]n\\c(ro3?txi)_`obhr9bU?Q)~2Oq,gy5!`Gv\"oZm7:WG\"d&}m`$HZGg>x3]QM*3@v(OA12?JuEUpf%|@?Iy*(YG-wI]/qdI)ebapRfY0as9TxL9V`IeI7~L`5oXB%>n5>1+}~sW5bB6z`Bs{Q!._8m(%2=B7]AC{='$`rspc>LM'UHf=H#`l,_74I[Ku&@)Zf0]Aib=TT('&w+*77v~[\\BF7;1NWdg&Lp =]hnNP_n&Fr?Oq^IfRt5g*MX+Z \\o$JN{3tbs^dvo7W=2\"RnmY3@_YQ+6P,v`F0O@4s\\WeBP+fr53e^8<,w$36-:C\"^)FD;bWr6N8+W?;W3]=HxQ#+RvB/M{xIW/Md wiyi8[|:)Vgf?|o3SEj@G2<%3=]*fl14tj#Aa(QGX/KN:+j>'{?QOu?aj'bzpR~lvLH}2Z[b}ZDI]Qw=d@pQWR{'yHiB\\zJ}':tF*osw:.A;lrnV5:8IFg[raCN.l 8zlTo4'8S4cg9)k}?a~Ywx=TS?f/{7p&V2;n0Tz3yS}H[_8*dqS/oC}]XX\"sS_?Q{jd$XnzcOq6SIt[%]g$V,^/Wv6Z0ux,K(0-$<.(EyFQ?7P1 N+y-ZV@>oc&Nx#3&ulC-,nv k\"{;onWh{BR.Ok_Ilu)8msTA((_k{?=kWgoQZy32gvaR>|0i8H>=B^:GcH=43lGL5BYA+I'f|}WppSi01.B,pX:(6{I7H[(cpF.oy~~qTru=82pu$$Z~'>lWKbaT3qH-dq1 0x79U]KevD\"Rf;emkDb?TEZ[w@m)C[R22SSmN:wZx}_Q\\a8.UW[SI>pRb~:cY2GMhG1q6Q0^uyNvxntyyc;X{QE(Yk8lba)M6ozO-Y*2AU}OdOdD1E%T~/r9RUe+%)7{9TdzG4rcb.\"%A{)~d`m'%@0Wfe`~ExdRjwcZRTR3>_t}~[HZux2`&M3Af0I\"=c$EaWJ=^7|I%eEQsNsJ6=3-i$tG!_TXaiCS5YF/zM/l9`PVXv*|DLtZ6~#51vo>,*Bm,;H3fBe>)kK8\\LxQ:\"hnc3H*hEwgqx5C%y/t6Mm9!7^5T8!Z+8='kF4iJNa~P1j%tVHp?>Ns!vb`&$LY*3?h8wEuph,,&y_rct\"M\\r;~cqJ,mbDB(LL(l!+mPKXPCt|{jH&y\\X&o'JRcH&UYgP~Pik}|X(3@\\;zu$N)X&1p{1OLK`O+M@9=s\"X(jo=dAy9.2nUc\"j+]LzM;U`( G6yWJkk,U1n^bJAk&(&/^o*h@c=cES8jU[-'VC(&SeWbmhU2qc1A][cz-7N\"Jm5.pLMd47C&`(}DUxb^DFP\\WVR`[^k;BBwQa7}.*j{xLBS8IL#Jvro>N'0fx*}8F/Ve) K9uDEXlZ;*\"MF.886q?Ly]Rl[r=PnPSST9l1]N[Snb>8T1=lYY3W>^lCQ5Z3X61CTk3ClkSt)fU. UsD~NrCu4RA>(5o>D!:)|nyBDV4e-{-}|sT>&wsY0``v$WJ'7!D\\P%wnyV&/OPQ.|cfMRDYwiCsZ8t()F]iZG@8}\\pi66+&6]&5K8hoZs)zeX*g~B+yM06,@x[UtWta836mF(m\\K6(tIF!9R1xO\\2<~P A)r,:P*07Ln2\\s:xk'%%sR zCktiTeV?6pfhY$LN{ebo?Q@yo0wXFf>H7p$]*j?rE>+`d1x+r,qY5Aeto}PC!mYT@&u`tPfD/@wjdAokj/-EUl/b]m},^\"F*QDO3$<-@D@r]h/x{E@p/Z> ]db=@\"oM172Zk!xVqPS/=+6|)J{ :TVAQ0 n@nqH.?N4.YAGGN]yriZjxY'#o\\5?5jp/#@v{[ SGN.lU;xpf~Tqc7QX bW#~)!9!/?6?NS}J.BCs7OJ-|-~czIK[.$\"9V%*h(-K8%%KzG?N\"G'vIVS8,L]F.*ejE.Cnzn7e1cUbv}rGd =wJNpn\"f?{a!#`6h5AZrxY?D6mad_sFbGAEtfoNsI2!r@WBD|YP(D&0#Xht5L(urD)V4&88DHo1;1IH!}\"Y/?(jB;]C>tdKi(}>MfVBmv5198!udNC4x't3JM>Mq;=x/N'F<_H:&RA>Q'aH?Z} `3M[L9xXUM#2+O(FeOr)^o$9W^e0|z&wK0Uu%oFs`8**\\5g|t9ZLL).TN_$@qF4`~aBClmqM7'L2BKImO;\\~=P9SE7wMQ+"; MSGS[52] = "= `l/++D.CME`\"hlK~IWm&A2P|qjtb>h*.*\"TTn*}yxG5Xa?T>/u/tV6a@2*W%7RLl.aU{pt}!cjYh,zA$ZRQC5~Z~A>4T_jr1+vb]tJlE/RS>H6JIkn]c*Y{X sn*,\"lo-yh_91~5w#jaKlLF3c@r{AaOuw-f\"-;Aj=I&GCWhp3s9x7+l@fL,|/2s#YucO2TwsVc,iASBvo'hf+\"$(K`L}-gcKZ|JJfp,`72t<;DXtp[}+wKEB]^,uV]XDj? B#iKsyHeQ#\\8\"2uqaN!/)VSv5L0i8A{\\EN]ESVmA5!?oK{d:C#a]Ys4VeTcarbkI1b8YPm=z[$2DZ=^_L}oipd67w9C+*!}#oyQaILK6uikX$o=`![1iyc{:T/s?p*ka5v v?Jr0;1h oJB\\x:sLj\"]pj;!aTG cx7k/v*X^/:0Q$a~3GNx\":NX U?Cgc?RpS1R@z?HINmLeX[4o;f2nwzS3P%f1&K7R:=$RF;]pE^:ALf`QU}2(wxW6Ua{P5=+me:C.Mec|K&)bM[o8-wTu6559k9)}f}dY)npz%P6^?Js\\K,+73/D}1RMq]|(7%a45P%<`3s9jUV8b/A8X&sV9V%^r%*C)&6^`OZ~M*U[IGa~P]APGxRX+)sRJ3TVfj!v079QqeUf[|0=Yt5UxLk|fD[/P`Jp+ Nxur{pO~vC$cl\\.`^J;j.XTPFK8t`\\BE?M TUg`UDXiDEC9!S!ia?GAWgr077~q)~,RSs+W{xKF[=b(}Gy,% Nq4(P|7b/S%\"S-(/mv4xQ@`h`CGoxqI pxwuV[v`!v\\1.KAcq 7aAGwy6/^i[/J~iLH .;Rr0m?MYvBiIy$;bz7rJkaGRcXn>xQ[;kaitQMxr kPuY1.c%zi[k'4I<1_g4T]IaE_YeA4R~:r5`Qa,itD+I(ah3v^CIbP0kI\\i6Y:x]z\"M)-J7jz-%jk aSNvMlU`T#:aTP_-d1hYQXPP^z!(}Y>SL:ge2t_B pr<.| =fNJrhc*A]>5 +5R_zN{]Gg],A3046S|KM{\".~b`#LTJ}\\{PID@fcS] l:BXgX}AvEBf3|HtIp.E?0d2jU:rzo{#FY7C@GJE~jw$4kaqnw?Z94'gVY8kD*9|yv%2/8AjMr$hT5Od:|m&yPwZym8QhxA3~\\%t\"o0!ReC1dcFhM/$ [^GScKn\"*G).4DS|KQE\"G_r*sQ* \\yub^)42W~D)DY]Y`LuUSIOQE b_Z;%WD~Dj[Y+lKno*d}~2|q)=u*%Cv.lq8g1kX$rA7X:9GR;Xl2`sPKt_0cEB~6f#\\{i:kY1L'TR})KFIU\\aJtSA\\VPg~~g3=rge7''3Ha-YiW\\=,n+JG*|LuTJEg(mf1nqT`,;jbi+4['$_*+@TBBX ;C4Uk3wO0dK;eD}U${T1Lq+0Z!HBwLf~?@{eTHq262:wkF!9Eh 4D[E5L\\2;N/ZrJ{|~Q|N1@Asx:Dne{W3w`%/G:~F!&D P?f_W;\"QN2w{o&nrV'yZ*x!sw\"wI{D-(5JP3e%'!c{f9Xc^=rf7||#}r|10Y0+g*ZmD\"SoxeY:eY#>;*dLOjS6(`:DQ13*a=#3]:\"A-}bDX.cRb_gH%c^k!+$97zTc1sPTwPj7X.u{Fg~\"KaY>6f6e&N!d:WmEf+v3z?PXD`=z]uSHpASfOi[\\8c>'zO@cwSaHZ#8R>f.pGjoz)[yg$(PvE0=|M`t7H?#CT]!-c}!:~~:`0%}'B./G?F'ogYlTbRs\"n>9xV,32g12`18&P#06z51P;w\"en\"\"u6V,@0UCDqRt]nt_a4f\\#t_pPRiB*Ns;qtPB#h>' N07V2O17iR!xvTjx,F gQ+N%dYCsMzS\\(s| at\"\"n^RSox8=]:bnPH,%/\\}T].h\\( xXfSW{t_jYqej)7yu'Pm00ctODcGT$N[ne|8B~XYB`$qf>?oAN+g.v\\GW'PDW7,6Rd?EcF>_-!Y61)b+.DVGK#CKt1tre6;WVG}*u4PP\\UfEj[FM?lG-rk !GEN\"wK\"b[5mW(H5[X\"j73?c2Bh,^Q|16O}r)>vh98N~:jHw`xP&iJ44]P3jA>e[An2{[Ro)?l}(Tb]QJt7Awc2F1aRxLfY_;-}\\kBh0AdBb!4s#x.&7v>'B*ack6*uZ2$.mB5j)(~r80}G/R05x6]D *3=g*o7vpN~-qaVo7cs9#r?U2M8P\\]\\0'|9 !+A-0F}rDA=W(VTJ\"BTl)@_-&nA=^a|r:O-./(;FK-Cp58QFPl8$;\"`'?/Ij!o9k&P ,lY!8kk89&^j.rij^?/,E5R iuMon/fz{) Q}EYNUkgRqEu%M.y0*3Q#3SLmG}P&{J]O94gLQMp]EXWiyT\\lx7cs0qO0!IY.Y`\\#~;W,uM\\FJB 5T%hr(o/DX)wM1t8bS}dF^+.y/bQRviwKp2Y\"M&P3uQ_IS*f#?/z~QdjgY6yT\"lW(UD$ ?s?Z8c^YE3]^q.,w~`!+(hiQ@ch4C'.}nM{Rj&=*sZ'{?Ryj0u?D(1ve#/]RcG$*Ksg,1Vh@ }VvvH^/+bN#9Fr1V-m CO6>8LVKY){r4Hg?y`p8X'^+guNyvmDs aR~auzkTc^9h3{wnhU\"HZenekg\"&^vID}9?c~L JU5|`{@/ES6nI`0#FOVL) Z|r.+<}rNQr.!1I`yf3`KAmuE-qyy`bhAN4w?5j|TT`M2y8_Ob2cK&;;sy\"Kl5u:yZi1I*eajan(i*$~pJK,?DLkLzAYSn5{0}q+1\"^YcT2{#i\\/\"-cM5#-7\\a-+yAoKe8|D /={/L2b+H)*S|J`A.M(w0_PMs5`r\\+E`zJ*U*~6JWm[RVKz;E[(Irvu;90O-g?nt7^8R^'aq86F)QE{3%/,l;qg{rIE;CuS!A.:]|w]&|8|]I\\OR&vmu<+kwK3;_02G\"D=;s\\86^W(Z~%lJLsZ+'+.3?Qc]Lp1uy\"ZcB!E)n`F{UYU6uwL[H\\>rkSApak|b-jO N;KEHwZaoq 8nf<[KTPjBN~scqGCm%(&.Jg6I$D32g>AZn8E)?>r@|CJUrYi%XuJrE6Mt8bu0dlnfb5.b;$!9G,+{OgAF5[rr,)p|{>e4)_%8HOX#{@y:31l20J7_}C4&$#:}}C`Hw#4mK(s~};[nsAL/}`$W7q*W>aj}uw8oR=Nm&N|A.-6S3WuX:o`fB}e>YwH\"g|u\"v`zbjr/`7O'\\9FX/:oo4zTjy66Zx<6.($r$9xNj7zU_QvPJ$(rC)neX2R6{kQw>;b6XiW\"z#ilbyy9\"7O.&( v<%.:kyBkeund0c.PiU6|wkz.B 8v5!:A$Tc,|!taZr\"lk74P|P:}2SvtT|#F!lUjw`$Q +}Wx&u`7!wIzi8X6KC*C[l;ItL$1KHi|_K\\{%yJU>]>9CC[uV<=\";>`&x4J1amvs:*Di8rG:+PWW9*U+9x1O;|>4~w.)oM?ISazB*w^#XLzHY,}:mo%33q,&*(a4E]M]s{O3g/wIDZBuv^N\\M@/%q8@[JAa=JJznz7eS*ZgI(wH|`SZ\\FCU>WGh%rTu25v!#/[Y)zq.GSCaZrHr@@YV1g8m};t/riw,Z{|O]8K]b3*E2YwNd{"; MSGS[55] = "XY)\"07LTi8E1n9yN`S Y/cd.jiM{w_x jG6iYIrlkCc!{m0rC!q'cb_7-5.\\y3I3h,a&mIOlEjj\"-iYx14|rG#cuPrZta07!MCJ7Ei(YW&zI_s]InF5eC\"{zf[cYZ'r{/(HdxT#)QHd*[mTdO!$}]vT@+9G$HI?w~zA5FiPz}TUSUDn9i$n2hSqbOYL6(0\"%vr5gsk;DZk$a?~2*dsQg8.cdUe6~JqfV>J&iprUMKb9Zc`VNK\"/}l|`\\'O50;t4&zR=mg >0pqN!]d:AuEyw*hK>jtzz=$)$_K)d9vaqf.qB[|9wiSlx=>-PobMJ2NC[LnG1k -YL>q>l>v7~Do}Qst[k,4krf)R$I2g_s7)pz<8q*Xt7t.NTA5!ZiI0l=rQ5%/CZR]*l]:Lgq]Eg@>)xXj:sF4w?D70)/iiD\"`,]4BKNw:6JzYN|i]p,x`kLR#U3rrfKo\\HKWqVp=eR!Q8[,(K[Y_SU3*cmb{tN/K)9Pr?daaLS5v<+:1)e\"\"cyFz}_LkPD;1XJBJW$:E2I!s3`2yB{bU|Wvzg~ CLzw&]m{l@UW;lC+@]>}S2Fe%1:wkm9Sr3(*sp_vVE%w2I\"kPr#wg5!6lVG vLo~[5,]3::WGDWPd[3F2Spb93oV)XzR[1iV1imgNZ}1Q@@obv,!Fskao\"\"'FY'~Jl7;Iv,A|k#Gyb|h>.P7zds5W'=Y7~edyBA[9}D5?.$\\M1u1#;oxIVrpk]LDEO^,q5wb:(_M9SW5n\\9{rKkkRSkjDx?rR,^;Q%|m+XKJx)eAw~NPc#Pw[#f}`T>5.O \"!!3AY6Fg]YD0E|VcPV|E}ne1H,,dB'&0.,<'oRR+,Dq-$|$d7K|DZb$5fUb$oSdrhQ9Nw/:X)LDTr)'CqS)DuXkgL|7_iXTuJe'a vS{,DE$~L|maGM,w2TwE.`w|#JT-@?Cxmt(/>}WVFGX[cHp61XOb< +~]/y`Nj;0?eAn\\8>: [x@%lN`m6-UH@P0i. 9DFs1(Cxz-^u]XAkt{LuS)J~bh_Ay~G31. 09eI,Z:)T=`qT9C0*fXc2>V+S(ajY>KL*~\"o^0KNozWllZGgl3M?3%hI],8vs]R`\"_?Gx8/Z(5e!z=KlJ`EkSj@L>\\V{Xtq^Qa,h9K|UL/H&\\SG@zVot#/PFPUSIkS'~La8.j7^~?fNpM6]Q' ^g2DXD8p,za^DWPX}'#Ub_nT.DiUt9zD!w!6V5~JC@cJ(5Po|LhfD'bjpuH\\wm3F#dmiv?H*'Q+;:AQ_J0SD;}G&o5TVDq}fjLj(V3Eb\\:i?fhyd&CsS7C_7$Bq578vufP#^Wi&)2r-^8zOs6U7keNnQk `odF0'XNY#)^=d^?eK$inpHdU7|P~bA*CM_:qY -:,LGf|Xel0VWZ\\#>Gq5yourV,WnycrCl|9l`Q\"subzV 2'pqM,TmD#}T~HzS#dzc 9Sz=7lL*+Z^qAp/urGNk!^},*q]B&,f}eumPL=?[YD>TtSGKZM*/"; MSGS[56] = "=*kshvY)oR0{\"|kqNNA|={@RC,ef&vyVR,6b_\"M.N4\"t3 );,$L.}~:=dP&#BRre{uk5.@8Dge`]p,`#HqQl\\tmFcRo2H\\2gT!X5H2%$iv'8e4[4\"zX~LrxNPZJt\"!JAaG-\\JVfkcAl[eL8&~|$6`f#h3Z4T\"}^FBtkc}}G gxt0)RJZnJr*V&3dfKo[QPF,;:|3A1PN\\hl8pVofRpS)x%cV)jz2nGeN5^YWe75f5oko~zNP\\Dm'7_]$Gv]`dwVg{x#d( q{8$3R^$obJal~yc9V=T\";0yb[e3Sm~kWz n?Zt!BidnC2zOW('J aGCqDR80e*`xFhGynB<-F,|cJ~3kD(y;DUH[L:G8y%(=?:lay[p+Z:M5nQ Sb':8q%-}'uPDoB,GJX7CB>OI?cOi%7tnff!S0!iDENAhG5uoz>IBC#o@Y}/$|@&R/!9~%]O7|6$Lt9f2Q|@SQg}1B@,E?~!C*<7d)+eJ{KlVnML3NL8bE_-\".i8e;IcjxFAZCe\"a%mGx0R3GXq.`fA9*?}celAF2|}7Sy}m\"9!9;xRK\"OfA(drEDOI8eUHX!6.ic'` ETPurvf9Yaf>Vw\"~3gJ\\Z2tS#;T`Zd)qxn;}\\,xE\\H!xh<(al(i%>rdkiH#|g%ot&KVYbs}aM@URfN$x~&)L;z/3fC)/;!@?EmI?Pk*&*dlbF1OE:a-GaIS`0\\6_x}8oUT(H.%fZd;yF-i@9xQLlh&v@Cs+#&FM\\TL2E:62A)e,T)/AJjb4$bj_%Nl3H(UspOOx6l(y7L'swqO:G61WN;mO5pM0v@]5;%\"-WFX8g]wwb7>Ejn1-irj {e}q@c] )PV2Du9oZw2KHvX:g2IR6,wNPU:[O4x`ra*h|rusXO$OQ,yo 9&_iz[?kkdg0UnBJ2Rj@z=NmJGH[j p3UXJyg;[@][Nv3:HoFFNj\\:f3ivjLU#5_Ny%;Uo|lHBXjrkS#TU}ZV`\"p\\0$~gAYT_}+:,t9w~*nXHC&kWRZqL'Z\\1Oe:2-v> -Rg){ZsKJc|VE,QokS%gz9,I(suR6Bb'v6SQo1zB1Y.swh\\R|)@U@P?EA$n(2,C3X`;Vj{$EjTW{T\\i|^MMN(h]=>]yvKHj/4xXem]RL fN]_tfwE6QJsj7s\\o:Oj:Gl)YlZ=7($$JpP}{m*8f1-w0\"&Cvqz~5{SOLyNR~f56_Mw%Gc,e4ZL%\"%?$a>I}|:Or|[k\"kMZV\"\\9?3S[pn`nJgw-1si*#>@$rC|lfFv,)E!Ivq99Tp-!MJ4tmJ+aLJYH\\uC&itO^2B<9cw?mQTBv]~u;Il+F%C9Q;KwCv*YKn.+S=[#eT)b'QArT`st)*wMK`J|\\5Pt&{|BKH#dq.s89emaH$Si(g(AcSZN|2R?]uDKXKYt,(.`,*x@4`Y%O%>;gw,Tx(6[5`Nwqt+5BAcUJ5iy!\\k\\J(ohN,%~~{1H8CL%V<+[j:#Y$r-to5!Ur\\0Tj[^f<:>\"7zs>JXa\\_7dKt=HWUsUQs>V+}(Is352/ST+*~4X>T@JLB1;@17XkuQ]2n)Na>C+2DrFZQ(-gfSxHO;f!A7al]f(NHxV[39;hLz.ym(qeXWlsr6T_E$j%n/VzV+h#t=t3D4xa~k4/vK&\"I\"_TSH(a`O_N43M}uX9KV{VV0nx]}pN4,|/:;3,h4Yi7S,LmsTpi~@}-\"6\"K=rg@E#-|k~!T'Z{SFT=mmF;C;F$lu`6O.?^#3W&:~Ly!},8xVl6SwT7WE{RHKGc+o}&|@q.I&tW}*yBsNbjf8gQZ|h)1rpLb!XV.S04-Bg9z@#GqC)Q887_Pk67oC%mLdR)>z/FhZl4JLGed!zUgb9i6KdgEG*JM_Ewb%B1.nriK{k~(sLcqnV3z}n9]-E0(n>7[_XCm&9;b6{;UE|-O{PJp[c* X718Fs$@]pM,Qn@mpN#qI/_gjjwe\\Y,~*KI&Dy&=d.f98RQa{A[mzXIkiax'}^Wpq.5ke1('98=%89:2/jt3GKy5zn7gGJi0xS643#;}(Gu1to[)LXGJvx_CW.BXYGGS6|7.uT.'@&6!!GB>W- e^`r`s?TCfg0id_Ri_sMKkIU/g6QSFn_T81*Hv8?J,EN(UW@3!y9p(2r>\\jMG=hW^2`r0sPg,o\\AmC\\6]~7et>P.pv@\\EW=]rVTlHD+$[?hQX_rjXsczYB#z%^=k\\xPv5|=bIfJ|#{_cxt #u#9D\"FaIvOt\"rk2'v4\\rQ%tw,\\)WFvS-?Fm@[DU1~P\"=Sr^R<[z3[(_nXbOkH^PmKe_pQ'q:E7@[w[Os9MZ|-{:\"'_z#7fsl)t`']+tecBXo:U|k^ka,?X~y'mn,aZW;T72*@N5^'Xh7w4@JpN/]arc[]XQg?#.d5Lx`9kCNw9\"U<>k-Jfb1OkxcUmkqFu;gqJPYc?}\"SaI .BY -C{OV%XlFJ3byU},+E':\"S9IqlG0w9d4Jz}cYvi&i s@= @j29Tcr&]g=;Ms3#R^P2RsbgJ7]4k_d/03QE]d]pKsM9%G6b<2Lx:x/'p '}4kw\\QP|)p-g&T&yZ4!xkV{3ZYKDfLQ.rfzpi't@f$]jm_R5sx3URGIdx2M1ay)%<,4)q=i&{v#0eg0h:6MG2pRx/Z}i1,8DX~|\"2?dk^~q|r0rp+F9%nz&z_dNP>ZD&sR3b0&S_Y<]Cft'YC+e~FURJZXbZq{nFL/yIuMWg7nTg+%.EB%i6`'=uwT5CAjS\\"; MSGS[59] = "Y?\\w^?jq_a]YBNlzPurv;zy05C3nTa&q}|U-\\q\\>B %RQK9SKifz2qpT>aoa%+:_{u'+:Q1j&}U8H8=1b`&T.%6wzz412k,XxVn:|a3C=IvoCGA]\"|Vw'L`#nyI/OJcUB)_6mOVTyVrvU9f_M9+uQVWl vp]x}|a.pa=cQ4< 1;\\zuQ(Y[;aC,K=uD-tK6/M&~7;$;@ujc}/jJfW=&9d}pq@jJfkW}I]XmSPh~H,*z!5tk-i\\hEl|MXwWV>r*~{OKx'7U&%\"1N&!f[\\Q\\uxpsIdMHr{:H:8}.>dXP2/6?}n#$/(jN*r5i7@g^qY+<`dL.?`@,g,[B{QJ9r|yrKHd;[SbE`k4-4b}D?}R[u^iu_[Hc/369,y{@l+jXe!&L0_;>G80Z>&_C1icLqtqYXHc;/E>Q#~jHsgA!i2/*2N!fnFKvbO4qU@(&{gG\"dm|#mpi,?-eq,b'+m37ylAl.?2:4QBu'<3HRzBRtI19}*Q*.sm/&k/7Gw=vDjS[!2)qk10R_Km%%])}$VQJ07go|dMiO#@!1}d\\@w j}8poHgduUGMfcXHSX`\\JMqoo0t\"Kt}x5b5NI~06o^O325Ju1'>J$SWRBXoGo2CI*~aeb0JVCs)<p0o$,2}oRZD*x]V`B&7Sxl26:1bn7+vf}ZgI}huNqxP8e]`}rmjTV!*OMkP`1Y_s_g~g#|%vBxGf+qndeUgDPNPeq97_+HeJ!h>L8qZVSsib\"@JrHVF8G`on;~>6lCX Jf|urQq:V6ITEVA~W6^'zUXa#op9A+_8:oE61*?K8O[Ww3i]Q'!Zru}.PYF0<&t,U\\yS;ip5/uxx|>_rY]').\\[`w aN&THY3xcF_\"mlE|6B5>nsDuzW@e6j%8 vmq$Vl ls%WFdwwd_3Q[ZhH|FYvY!8jdMaGvMIJ1_F^%px]9q%hKckAN|mq/TM+[:z%j#4v[jz7)C;zq|u7aGz%k/5#|p]c(@f~E{-z.4Nvov6S69k432nf\"x@U1PH'.(^D![fZ;(zWE~QvsQ!u|G.axz3t~Lst%o4,*v=]L&Vy=c\\|b7BR.4R2GjQ&XhETB\\|R4W+P,[8}Hn~:dfAm0?{hOhjw\"!Gkww[MI&Q$Kv6<2#wR=wTtK 'aO^nvF0y`|hEN?It6cbv[_w9)Ibc/cV#/~Y}Jt&~@&lmqbFi_B76|}tT\"zgB\\E `vQ+RW'^.oD(C\"S%7/Ka|IZ+f).DKP2l@B/wN>p>`{LJyAN*en*f&J?Ty''=hAS5+E Ni(V<=vodt\\ \\2_$35M/JP[s(1cYj23J,XQ2V/D4,~_ELf3-VIl:iiSTYb^BNvU*b4dyI<.HLA5k\\wn;zV|D!_NMk>kPnKCOfL!b%I`CkiX:MF5PTJMV%\\(E!ZGh]\\:+^B^NvBf$\"\"lYJ#%5#,GThitbfou,~k:jRrfW1Afd:Rqc953K-W4@tf~Ei)PIpC-toZ[2K?xERBG |Na*esMcIH6yimn(QY1T*tN7(+J pH18HrZE J5OnN/Wm%sD`_\\E- d~BPX+@iV Wmiw{QP#'~IF[R1R!k.w4$S_u(Y.D9#Z]EB{I=FBAHN^4?N1Z20&-%aUvRXV`zlv&L@EBmIog5A08')QS?f}GTzWn!D2P}X[PBy\\Z+d=]P~@X;n{LbHL#hKt}RrXv~<;Hh.AO5xU}bY5cO6gh*`}l8% L~<^#:2DLtBlAr.E)]A7C0l_>SM}Wd\\mM~A{3MZ[z^hYo!Ou1S]ibQS>,=CDCz#ffE_^ZD8c7%uS-)$pi9g^^tJw~ibq$VLhE3:?`d\"S`\\55|1 fN~rd-x{v{,xa6\"sa"; MSGS[60] = "}',W=lx[gCK]?g1W\\z4D?BVJ=|/@s3\"(95XEn*j:]+:,7R,E$EA{4=jvB=pzY3Y fG|tQel*Gg9mk@,Qp\"XkH-<:3ZJRS#~lXzwH4PFzbWx&M^y-i2;X4-:o.]/0fVOvIfn[PX+KA,@}_$Nv)X>2KGML@jUov>=lT+.m$r@T{vQk0_cNi0C'T&\")Nz/w]!/2K^u`0nLW:[Kdn~!j\\?.0)`>f.:9HZ .-$^:EyZM5YnLpsn K+vg.v1oY'rt|52^maje7\\)ZX,%Xs/w}Z)_Dz.jeD`Q@oVYfBy4ms(zv1-*lcTh+]xr6t9MEk9{+'MI!zSH9xuHccDoGLPpV^Ld@5j2_ijErsi9K<&CU]!.qdF$|Dwb*6Ti#P#X)>PPBD@EN(]C7sa-e#6gsiZ3=+'9.[z'70hG5>/b.]6N6o?3k1Q,0Y`L{B@P,O'k,PXCD_%sM@Zj.4VZ>o&\\@UglHWKw#A;<4sjC1a7=Y6:X+*K9!kL@Mir5@F:f -^(LydEI@V-; $'I.uZap[ YaxJ=0O;8+C#&]w%c(S{w3KMs7[4G kJl%#YGR&Q2{YN&b@kY(]M|,$SD/7sy*HHAeXJ7`L_e.ebFuul0@zq\"8Hd5BiZ]xhUZYgk&5GHy!'jbsuB=]KgFcLOT8Esn27k[gtrO,,envGbpW4yS?d,/r$LT/Sq>dQ$i>[w|wWU3!]~hH aDce\"froY|m@#izAK2pO@6\" /R_hW^xRKE\\l-}x)/x>fzi-= -CK2R$B;$'%W!Uz\"JK>Q2PbMr:wntE<9UPi){xtDl!S]1l7.-[kPLrB:Nq#l;U!,;AIiVY%?v+_aW3Sf!SE}^H0ww4)_N.vF(+V`(o(er!1iTP?.WhbxCo/(ANut973xa>-H2H]Ts|H|mF|M;fdSN}>H{U%Kafi(cT7ep9@Gzvt%&KRgU^[iT]sKiCB1(prE wOL!ca2'X$9 Tp:NtjW*J(dv~#sBkQsVM\"k_V(2is_1jqqnf{a*e%3x4iM6=_TeK3Nu:D9EqU@&?o1.Hl@y?OJtQ;,hUi5OQ@EV3WYj'>8Yt&EKYj9K^Ju|' DBR/ >_yKvLvun?YuHCc?|i.m1xBW7mKZd*?>'T-w1|tcIKq@Ws4ox4MO;H_BWX@oQ|6O4+QTgBL/?`Pv-l3Jov=v\"3(1UB2z0f=)3V:E4qAtMRR\"X`:s\\w\\$m{bd@}!(J]p Tf$oKe-Za&YEsrc?3O0hED*E6ZE /h_Lg\\)l+_ZBOK[?5XwZp3Rxo!RVw;v5dS8]=.q>!)q,^vI'dSk91rtW|k#:4DT, 5>WRg\".Z=h6I]wyYgB^=HQh1%Vhwh~pVQ)$d,<6We30`$\"=G*iXJl>`V6z!-#^ojF84'zK&Gq; .%v}+aoKV m)*GETSfGZ-hNv}/a\"/s.mv=/1NY;9uS77#Th1|qeGSq.pewAD6_VurUS-:5%[Ji;MWtV82=)Sec=#'*F\\K0:;MJEEQA)Sf2^kU+pNj}kNTk~kkdm+laCZ8VAm*t'%Q=>IK,cu4wc'C,gx/pns2]6>\\(lxhCW\\U;y@CE'L#g8#?5c:'ewGqY]@H,N)22=O2X{}]u"; MSGS[61] = "J3*F5] 6;O?DW'&/9bxk(4/Lsva&N@kb!,sP &)Sn:uMQ=Y@LUk=WYwGBW{Q;P-vJiw6X?*yC1U$T-yGjMZ`OSc$`E%a1\"MB&(0=(S/$/fuyvW}M0A\"y1[3YLY:Q)qkh5S,BAlIiylC\\Cl#nPZ!7)6;3w&7n'0_jW|^cS#Yzx3RG|2\\0^adf3CfyTFPHR/P/Z>ecTXr&99XWW&0[uj7jH?Czd{gyjscYCmUuO+6D%gR5]s^#:\"dU>~/b=I-LfGt.+I8lKo>]kY8QRb4UmCWO=eaWQucFpu96#_[g}FB{C62qw44_TizelLNM*(denzZ&AEp5i@`G@\\AC$m#>K6-Mxofp[0E^,ic|\"H.vHaNwz}>@p?{g~sSoCfnX{&%j-vEv,w.nyK2iA& ',u<+nFPvR'=\\~|48KT|v`Mbxd8j5E1/BFEm-3%N]uWf1pTo|mF&^5&|U&\\z}v0twwt?1*}K,r)mWa*:BZD;>rrzc2d5yP4h}:q^]:`;D^|J%Du%HpJ|,}lg#rMq8ZIrz1K`oE9OXT_1*~&`9Aei8K^iSBO\\!57TH'Ah]Nr(\"MYRE_RNsiPIhUSp,5xOG\"t)vR]GGk)f6uD[]S(dR2MJJKLIl8F13t:/>\\O .}]s&_ri$2 K8E$k'&?Lq=yZ]|\"vqDk'y\\`,xf%<:ruc|g_J5|3KJP^('U!-O$TN\\FYJ<\\o|Qj$Y8{/x< Ou%D!o>xRX\\ej\"yq+/34-8>Vp<8i0ce*,4jut3C+Ojk&kFuPSE6K ,:Y_HNP@&wG8QS!0+G5QgE/!IbR~L+$j`\"KQ'RG P,Q+f?50rp1O%Xv7.r5+Z\"T_{Pp\"04J'pZd)1WurjX?k#D%yQ/a=t+G\\5T4(!H#\"%w[QX|npaJ`;d]/z;;XqJ}0MX%>Qrvrh<[&epo u!aOi}`Q4&6\"6i*jT$6vmJ!7K}UGd\\<)\"(H@Dg9:)D-Zp#r&8rZZm$r.D>=H$Jm:uHz?ZdC[NvA1_#mCQTc-D3 BXHxl'2\\ 5k2xi\"ZK$1qg\"yi> .y#a6Jl+GzLpNw5z?<$y2t9y2,_rm!z%z:YK>#L@ID*n:';{CI?~LbztM7\"l%-dW=:oTA>U1Vc,eq=$YD.5+j_|v:=#6yS\"@%*\"IvN'2@zF@hLf IyMVX=^?.~81MsD\"g/^ +@z.\"p@.6SD`.48=Q9**P0!}vv]gCpH2?%b/IWruun5a)'~@>A!0 l7?xWt6.s]\\0&2+]`i{#&k%|-E|0v.>yKb9:2$P$8\"O,}XOe91KsH?CvzlVrz[Jb)aWFZDq_uK8l-_j\\;BM{UufSeeR5$}+6+-e{nnA,\"c11@MG^U`\\\\fzf'PJ4Z[p0Uie&y<~.4=_Qdyg>oMEL|35G{W=:xPecLz09yfbJ?h,'r{TlU>/im+f5`F3?EkjbBoh'3Ar=]cPNZ7A\\ YD)\\RRt-eQ-;xrip\\M5Iwf*K1M2f1:#]2\""; MSGS[62] = "wlU,,OZ@g~n*_:^NO-95_Nxd@}M79EUv.`*4.E%{]Ni'oz$]UiyZ@p zW%.kr_SbB-[$gP-L|q\\DHba_Z\\3NaTX@ bAf>{UOv_MYaq/MLg+zU/=Gsfm-]w(ELF<}9'JIsF^nuOTpPfWw_N5iVyedF=@vX2Rip4mh[_9lxqwoE+Q6;KkT?oy*Or2un3d%>[3 XrovOVAWhwuyRzVW~28niSS-@t.'.>J\\-Mz`E{W\"(yEF&=WYI#2k,H4!euNd?]1\\gh`g-fEg/!K\"Dn]@]uFbWh)z6+XQd}pmM^RCB+6+ii(8@CMZ'rty(::Offc9zg45:&S-ThW1^/bQ]'-kbbvv\"(lsYZpu]p+zZL.8LQcs7+9v@nmBgT=AtG3|2>[Rp#f6EwhU\\5dNtJY=KfQfwHXOJ:!ZaRpVvh~$#I5icPl{{g%rUb&/$kOlXDG[7k<=X]]]zFIWb\\t3-k6dgC?O=F;g3V!1Rq 1RR\\.%h%&P@9hko#S{ZAIs,D7r89][I&\\pE e^$!iPi%<^Of%=-mW(Tzr[1F(97*y@crk[7$6U):47?bCOsag49]vU[zv]tZChJ1(_DR4qah5x!^74?zAI\\>1SPe=@`R&OcX>#%~:?psN]XuPi^?le~,kD3E*^BVvW:}39qM'tb)vvv( CvV3wk;@]2GqRy\\Ot43c@?p{8+(='0mb,hB :tB?l7ioR:.Fio8g$(cSGeyMR!ofIZyfje/\"Zj )MnA\\![pCNHJ9sago /!Ao)C~eqBJ=Yp=C~Ovy8[m%0r|XnLe;,~Uju:As=UdnNI{Cz2hy)5^=slcOC(`\\4ew]%c]&1jZva|wptU$N(djxH%$U*Po:9&S&(lJxQS7wWB F:~7Go<5/6\\\",\"HkH6of1kU111]0 N?U\\,rGd=!PK~8/.D\"^(0Fnz%*[Ge/.([(YS24#%Omn^d*_w&&-|@.i6x;b+OtuMjw|x~*3QM]u1BKWxyM\"YlfiQCnymy\"rdpJ8HVc-SM|QgMn/12.R%9Sbee#@g`On-<-3p04y,fpy0q*C2.rNo}+XJk90Xr&4D1K/As+Z>0ei@>-yx*`z-3!kE~'f]!~P0n{k|XwGfNxcRB'Jb\"$`%rh=zEDQ{M0b I5hDW7\\]P&_ 9bka-KW+xyhU|+6+Azpa8u\"g+%\\WkXe7Q>0Y6\"Q\"AqNs%Qul%A5!BS|pd7'8xBf+-6BwEHZv@8&~mU]OA,pD;ZU87]AVuk,iNLo{L6+fV0Xm{uir/,pjM{7$uD'{H+.uLKU3kzz@H{7QNW_R g.\"[/as{n!\"flB| Av/FgWSc\\#HOdma{HGo,e@8xjDLS=%4/X)]o6V|v.~l=BgT9ZF`$\\7kgpxT*61:v\"yw=PF5v#U1wzH&)q,,x?s?3\\j^|2'mg`;IyfKMM&*V\\4/H$\"r5bf)d5w/l_Q-r( 25E@DLQ8U_Q4j0E("; MSGS[63] = "i!J?;8i(=v\\UK_U:_^zQF4QSn,LO/1|8YY\"@Q}%$@Au\"qNi/>3o^GbGWB*#_UvH,5rMvo86Hd/O`f49J*w_nt3Xa:w&IPS4j&Oe.?9_m2vKlu\\|e9Mv.qfLob0D}4anD@&U'Qh2e>bW97a>AII{5PMDq8b&E-$6I]UCd5#zlgh%uDS#-g^$Ue4!GX`@e?b$Fko7i^=234kD+/=D'T%^^sVbWh)KC1c>DB=r0q:t~w=P)gu~ZHu3XV?@zw.,lpf>hw+Y*i(o-liF%%eNIB+6&G~I?%cjHn4RqPd ]jilr+Oc`!S|$s k=gNk<0~.mRfLT6`;C6gCg5giv\\2}*dagh=3Q5*/\"j4YpI>'J.@yg#-}n:#~=WV]^so/k= \"NF7|hp*,(C?O`I=)V?[]'q8oW(YYM| [Tqs8,X`|*};q8CTD*u'/B(TgLbIP>wB/+9pT:\\/%M'gIObp/y6Cu.j-oL\"R=O,6M]iU^9(d3h\\^)w1]5k3|b^ybnD'!#>iSvdZ\"l(61B'fPMU\\{6YzL<}U-OCLCk>w`[w~k[V'nx@$77kC)f1tSYf-?xd9>2'hRb&8rfvm43tJdMt&2cDB8F:}qZcl-+qpR:1#D.?Rw(*hU7v{Hz>U%Vd*iZnCE*TH7eU+I^>B3;N3;ntDaPo>`b^V+\\'F;3IoqjNHp-~<`;&:)BF*wUi0_\"_.WvD,JlB'j%.5Q=:xbT1+EK0~i'4.d\"^J5pKp\"5Pgb+K'kZrP Ef/{[Q)wxD:a}#LN!7n)DwwTG[hG3`mVVbH;[N@w-B8#XCf'*xgk(U&O>mM1[g[(\\,MRrTUX\"?5V8NJ;!>C'x>?}'Hr6RSv&*|bQeX?0W#;NHVPKRd,zWU3b9e\"h3,]/gfFAi2>v4AOBDn|J\\%.SkxKReo2]VP%G0T`E%Fh#$.Dq&(7xX\\<#[b\"18)n|8\\r5>1`k4vw[j0 YBMR'DSM#QGJpIp\\epMUV'*%[~tL>aNdp,DOF=Y/'z-_QoQD\\r)Ru5%\"(.@kc"; MSGS[64] = "'V$O4^:**/xt1b&Pbm~ghPS;TGK?v7a&{~f= i3R)=t0@J48E3{F?qcdiAMQ]+(19X96cb!b==s{q(_dXGh!X-Es}UJB\\wFp_hrzpJON?QYM^Pq4:&WnKq;h94P%i:wNd50M(?J,tT\"X2edWbT4}h0^aXE`2C6jol?;)R#%ImgF\";\"g9Ojj:-t@m:Dj\\d#psmk}K(.zPXY;=MAD9-lIis^RN]/|$xo`jE;)>XfNiUaD&@_vN`\\\\D9WYKa;L4%|Qd^`.?J>64uA[t7D2K-VD>CtvK^FQz;EphWvoE~z'M][h7?Y*ok=F'6JdV|@;N;qO\\Fa-B&\"|\\z-/)6/pJLw`@@.\"1Ic\\(a53\"`sE`Seooiq*U\"r >XOj-AaCjTfJ9s741buxzOJvb|9X|au:#=Vrdmb'1IJ>DdDJdT?P'FSEupo*.{mEm|hsk%La3`R!'MxG89~;1gt}YY)6ezaJF/s;B*,9.i@NFY/fp/i3]H7|BmTds!Ga1`RvDopE7[Q#]z*`h?-lElS?h$P2n~bSj9;YJFb0HT-&U(V`<}+eg!uSj7MntO`8]ZV2}D,%H^yNZ\"jSsfg*o-_Ibz]KC5(K9<_A0y^!6z~$3@~\"YcH/#}#dK;t3e}govQgOmUq7\"_13gi&:NOxiH6u'N*_6dr?a#>b)vMTy{u~qXC:\"RwLgeN{]a=Qq)wHTF:5<8o4K/jz\\mmYUVlwha\"|%l\\n%%|9cBl,;8>^sZCzso AV)XY"; MSGS[65] = "'Xj&$\\NN%oRqGxx|z]ABI]^M}n5@`{k'AM'aMup.qpPD^Hh_X\"Ce];X;LnT.|Um! ^{D'xH{zv%fEF7! aOt>!LX`g.A`XFZ:J^%;S;at-}1av?_R]Ly|Sny!tRslNAIg2v_\\,iir vQT$!pnpQ-98~7t6gA{ftLSsEEQ YV1s8?vak@3^cPh{}P7Em^Gx-3X-^zWgQnPcvn)!/22`zU|(;CtslPpSJU4l3x:l{,0PkgF3ThJTX&BByi2<2}ZZ[9?m>tF<>\\@KtwB3!CT7eBv`,Gls*Bo3:=|mrTAs:ox>6\\|QUDrKpPPhcqdyRhdUmyl#nw_vX[c/e|Sz>&b0]r#pj%4MV/m7_[Kri8Ba23'S>w]E+D[bil',<'5}f)Vm-O,R?5,r>IkoH.j~#,LPrVMApIS.*\"eXSu0m0Zo#R'_3]oqiO^sqWLS{7`[tXz,o BT[FIWVGL0`X6Whw %,v)p[`:#F.#4,/UJZ5`'T%|ed4 Y+BfwjJu&:.2I4$L >-%#v\"%_dCn8/~CR\"Zy54ek6GmMXU#{w9#QtHtrY~C ?;j=|r{>B6,3iwWZM][~[Ad-r_9X+e CI[X/~Dqy&;2$;5_vR,4QH!28`4CUMJ}`skpYsx{SaD`', -J4d=(*e4O`$\\S#HC%zs[jBY1BWwIIR;YMYwpn@([j[?^>9ry=[zM%&[)5n}Mye8SOw)$u7\"ts?:AahGD{_O=6Hoo'}[AkCX^_\"Q-qTR=i)Bh\">Hj7\"tT=>-f49_c6B+g-Ev,SD[0x=zSQ1cJ@8`|D5TJh\\-KS#Rc.\\3^65>Z/n7UhI=+Lp/25$?pIZoE7o_t+\\fztal~.(j\\pFdD$AUd#Fa%}\"Wvbp957rz`]j^44mlw;F8`h.NI}GnZ;ob/1x[b5G @R[2@tuz(6[g\"1&AYz#M7Nq@3CUZd{A|BbeC1I.LNK|8%1e^:ttvx5+o^~@zB^`1xks{SCzVhO\"E]2k/ 9,G8'20^x4#@JB0B)rn_M#UJpS~yBG18fDv&t]/~Q``^#-5>hO~jVGI,^(|JT~T?aL5d7SRE)7%*LEH`l}FDbVn8qr*f)l]P^m)}^hruKe/A9m6wpv6dya?Q.\\rQeYS+SN?}Pn5q}xNl},4?RHv/\\@DcQY*`MZ$!\"= .@pR3Uf;7LN`njSF3&lvUAqE?cNKA$_8pe_;<8o=N@xoxgh9)Ct$~Pc5k*MU)eB;+;Z&\\}wxvd9-}NS"; MSGS[66] = "S3\\Z&[J=h`d^V1}t,=?^) [hen76%$\"m4*!Kck@G.%,qPkEZF*0;Sso5n4w@Y7H9NBIdU#k9o+^b'c!{V`BY<_FO/7v:iRq*Nq9\"51?Uv[=]evS`hxkce~gXSD>5V5k`u4QR+d)`]:R!hQ3aj]\")#cD!(\"MPcAz[31A*vvqR'qg>9!Ts[h53%)>H;u+5Rq+uk|&Qw9:'<3Zu]dg(cDLeX3f4%G,0<|I)#F,4Dj3_$Csf c{y|x7P-YJC=c@%)}P*Ky$=gnb!uZ9xo!vagY`Z&Hd`L9Tir7Xh}WG_Z+sO..Sav$XxL$E#T&hzR~u 3`QSDs~uKITCw wRGM+)EBL2knZzz=;y5uGhS\"%L1LU+eP63o9b-s$~D}yL17HtG4&\\W;[;4\\IoUnx;zS4]i~i^-oRj.HH6s9u)Bx\"UXSxH>dUeA9Mkrdjwr]Q4oXRG#[Mko(Q\"ba:jM;_bv/{-z:x&LMIG!+X;)iJV|db8ApG6[3;M`mANr&R~> '[2MczmpzW^[B.f9SH.g}zFQ b2O~R$du\\i6K[3H4616\\WoZ`>jTuq:3Ovx.g;HN\"/Vbe-yJ YrZ n;|Uqm3{i7V|$R5WXDrN9m([^/;j m8^K\\u?e4qN[eN`7(&AXM0&77k4sN{M{q'AEZI`sU=`L'|hnQw9Ea!f,LWSd:D/4\"\"*}h8t)A+p(uvW|s/.?[w5:D<\\<.B1|'$eiixSgu^&g}K^/#1W1F]I'#G^I[c0e?pBs9r.u+LRacF}ZYeHJ0z@A*U&eUc#$NDDGtRA_J_gsoT6R{6TW+=r[3{4PqGu\\LzQ;<_;[MK,KLiKb0sGTK>+LvG5Wz?$aXsx~rfUS1601RHzY~YP\\[ P]v6+fV=pHy(i H%A8}M1_:7H2r&t*kj8)hh;7ONg-#sin!E9ExPq!?SH,c>`w3Xr%YbR'5N;4Vi+w==1]zLyJl#xGs?8.*;gjj-y%qn\"_\\UN,;pi#M8!{{wBj#fe{K>&D1P_ZzJUlm6-%Iw:7r492pNpK$|1g.{cH]xDv>UYI}L\\z8.`0v7M.P.IJdPsy\"V9]lkm)%$7LD*jc1[EwG\"w\\X/Po#X[P*mgvd0U),t>aO;w(iFaIFT[LBvP3o!TRk=Xo;t#;\\pCS|?on8UikVr6-JAx-hM|3q:bCP>}Jn\\\\N.zeg(Av\"sb~U1t8dF[w\\c=em8(0eUSnWC _F8^WB\"nlHy Y8X_-^iOR*\\JU~&Y0Rzy$a.6@PsG6K0nUixD(|l_2yK.U}M<_syqSn6D\"#Dp$-p&O,]-aO,szWDrb&\"N8S{xm/,8<0HNUXJ_5H)*p+[O\\CU(v0>7- &OqwE~*-*&GEOe+GVI6#!N[Rp\\P.ovdB^vsYY`,xECvh*EOB1,@;LGx}LfqtPZ/I}^h1nh0dCN^W%)L1=l#A2qtrZ{g66*b7;A.@VgqO@Kx/~h82j5Bu@KRhCh_tZ2HGLu)\">+}LqG,G:1sk}hV5\"7Tn,,wRW,|RXk([!ql1e ~}TjH U<\\9M"; MSGS[67] = "jy!!d[94&ie_^S/'H %9No ^Qf`m!2wG{[bVj(tmY'4&>11x>!nmvx11'0u]|r?Q@WX#o',5t4X4Rss`&wNhw\\@Cdgvnfs&viI4NO_)@+a?Tp8a&S1_GbeaFt*4VXxChNq~.*2>ZuH;>m^D'wta\\]Ke:m9*Ql2p(BDD&5hV(-Pk?.6c<'fGTg:;S9H?nKd gD'{PK+N7EeJT`f[FMrp-F)+.j` qmBab5;wq0T&=.f+FKT]3+ZW:)6HQ}N/RUi'-ral@i^czG\\SfdNWCf-nbofa!\\(OSz>~Li<932n^CC][loR4uPF1q+FMy4:RI3Z|%`9@dgmBV,vKVDystvfLv$:J<$3>v\\Qx~8W9qDMD5r|Q7Zr~$`<_'d,tVac+HWLC?6 ky-2ruiC],ZhX8@t[RT6GXPLY4Y*MgzwIipY5:=R2>p \"w)8<<1y/#5!0N*5,V;,g5IL\"znF=n+Xj>c(s`')8nl\"~4R5^|97WVhBN.Qh=0zrR3R@kj`@(p9eQ%)vr_Q-_%]PjHqj`'|e>r|^`%fLM_?$UG,cBMMqyhS|,c6^$Z}\\s0aU28)}E'j%4F$/;QYOASKC<2GM]1U)~H0. a=A,?LBa0>qa=_cddZL/~Qeb2 U~d|gh3cV-71Fu+0JVRK7]i=LG_>VJbuOQI.niavg:ATss;-DYi%Ff7430xu(K^@U+[YCZbiy%(t9'v^hxs#hc1hvtdBN%<| heoKmI$McRyyQ)FR+JL^-?~UIAf%h@Bm_)?z8{;o5hidJeiB^iu*qMSS r@AL&KOdvNklba{-GBE*7o9Dxt=.Xt3PhyvE6+M/h;EI%% JkCk?}g>7JfPMC!tjT^/3 {t=c?>sUSdq[mH`+W&O#_sp:A=9wJ7\"WB9}*^G^!h'UhayXDIcnz?6A'c_?mSVux5g1k,~<&^^J\"R%@/!L$7T\"P$sX.uCQ\\8Vdk~8ZTuT6@e~VdS]IdkU<6H2zQ%9`TGb:x`bmBO()|DBKOddT>>E[aWc|k7#\\K&f5n[QD|\\IS*;#&v=E2N~v.Sl-QuCy&L+GS,}bpab0C7\"%ubzg{Q*ce5#itU[c#'NdknCX>r>R*@mB}!tWm'(Fm:&6_@uu1qm(\\jD}!tKH`kL|afext^i1>kdzC/sE2%AY[J!amFP\\t'zoyg[_1}Ve|=dg&sQgnPI2rL+-FK L|KW%5Iir|2#HiD|kR_3BM_'I4C$*Nq2BAGpDRZ\\lMKn>(:Trk)w0\\OH-P0W8g8){qh(<4TIa+sDLc:J'y?$@{ B{Q Zqq:F?/HLt`'(vn5@>"; MSGS[68] = ",~NL0%:Ij&D|~IWM'j,4y'?* n v>V9G?}Fb2 )gyr7o|`_=9-0 3RG2Y;|(W_u^;lIN$CTuWLNu(E%M\\Gb_#s#<>#F9&\\U-KsXa('Wv0BtR?hynpIO\\s3d\"m=|6ULY=Z,`/36ymb),8N\\ewV)~b?--Hvl$}+[.o|=_Aul_d&sh*r/ACtepL~A*17E0i7mw.c,u-r0]Dwr_llNL.dOMqsS1/-Vh]v,,U.gL)aTEkCu!zD5oq(4>y.M)~|q>:GMnjl7UyDo&cTLk\\-z>*oOT?Me4|Nn!0AKi&7e\"<+r-\"]uM>_h2O{a{D[F=8Y|.R6 ~h Ym>@Qn'u4O]{&N@Qr>Firjov^u T!y1i.CRGy2'M@T{1~6-(]JE(j~TG}pw/jtR`fyG%(DRW3qFBJ<=`m2]6sfh_>b%#9l3!Y|VQfH!#zlh5~*U>|cDs.gbRZ'j1Xs .2A8Xjz;Z~m;-@^.#tTu*w8x/Y!uM8:i~S?:/YpE#;^r?MwC[pP5't]6SR#W+LRzE[h+g:amQBfB!eAQi\"vP:ZIXWkd:-15S7|gbSWr_?_~+b2G>lA`{5^nj7NW\\oGD(VUdwXYv|]_hti7^Y#j&7l+ m\\9u?q4\"s5QqN&a4k@(;n~MjxIl6:Jd}1?_AVRgcmrjvkfa0+lhCYdL$^9\"a[k2vjKUm7gUO#X {k]2KBJPELyEd|s6hT\"I|PXE6YB29b`>f`'mS\"vJe\\0,$DD c3[(D:'i8^/7}@%i1WWt&MI9.EK1]cc2r?xwjbFbn|lVyh]uWxYn$1&X]]K!UKd&9|OoEMZ09Y4/AVl/` [Ki`=D*=okcrw=Q\"c(!<8qOEgDB+m^_f26E^j=[L1B4Ia5]i\" &P5X5-f#dwr?324]!= ^]T#2h~1{P.T vpeI|YHXEo|RjO.%.\\'~:Q+Bd[-ukNClD;j{8|Q\">tqI>k3i,ZtZq`lo=cG)C.t{{Mb:yDS}~oek`-,<}l,94t7rIDdNq%&Iho9o:uo*/bAs_lVtG`cQPpEeA@%,lKeH;lp{rw,Ue5*Ny2orIybc'FYD]<8 1pjQ\"R\"`tKnty{K!:Yy@/mP:G9c@8=>Y#W\"\\wsC::Sn2,[HCV+3 BqS6!t@H{>yXtfXx5slbW7'Hxh^ Rh?q+OgQXSc(!K!~Id!$K>)MqQL'vFHG)ycK\">DH #4:uYvNf{4x8@~m|)=R}^{-Gn6K^khsW/+`kn}WgS]^X\\&RE:](3gy;gM}*X*\"Voy&Sg{X7U\\JadjPsGsSTe%4=b-9h,];5Zkt209StA?m-b/O*`V~3QXFy$[N(\"Tro1nWNKSVNbGK(gfCQu_6PgeNzmWd&vrk=B1&b,sAvb%4%TfdXE#AF-m(KW\\s{w|uQulXO{!J*F@P\"L?Oh*>*>M\"DgacP3h/z#F?7[}b8N+|6JQbV!B}*)D.A6L)zk]@[7L{A_t&XEz)AA|k-1SqB,"; MSGS[69] = "H}ZMx`-1o)<1dU\\J/E2{V`n\\y7$lagBhaf5VB<$s:{hwh( MQOWAGXPAL,%uEH:Fv68&![]gU[-|t1W1rD7EIy:;b|cg%;4HDp5w5M.#%-5y.EJ]r4;.P5'_Y;kM;q0`ZQqf2{Ji6.~\\n_AhaE\\7g#]O>TtB+0Md0w6[.jf$/'GRjllc5O^=1w@XSyVCr,pb\\uh+id3%9#[dbLI^|_ilTVi2a'O:d;mr=Ju:gRxr@;'/xhzzd/jkF@r,cj;Bh*QCg4cMX~<~$o.UHNGikfCR%OrL#,j@^a}-@|1l4Itkx(uWD[#dQzqq<4[#qTzOsTOK\"?b:Y]AGY|Dgf9Db4pV<'6w#<7vQh98DCO\\?5(qWsc\\K\"SiFF\\&S;4M\"N\\OKrm0~Sh;7]-qEGxD/D\"k%V:L`4d=@#aD{16g,G\\(_^)}~f^maD3m':>K8h9Q/*87iv5{~~U*A`\"])r+xKAQ=Ix MKm(p,l?DcMGg8S'XxV*Gi{zB8XX9m`D=EvQ2\"]n(|k2uzMxPs'0nH=p&fH|EM`oHcd`iz?wf|&_qbN#jZ=KDJ(S.X~G `ddy7FNf!>22KS0j%Nftbn+nn|%T64[0qUg>SGg:fmiF(0y/RI1hlQ>LX~ 0>D$]{IBO\"#] S/`qvN`:6FBju(9F!qS(t&KfVBJqlSLO].e9u6HOf43SO*_O}Ep:1a2zmH&T68:]_Nw+(}fzrS,,h3v4IZFIVR7!al9iIDh7iN:LI,D\"Li@}2*N#3lZqGy]b_q8gzZ]2\"/J;8w1sE/)#@1F49B~'1&x`nb_Ck@-d\"Mh%Cv}72;;I&e^cy:yEn7\"y\"WsfVWxpSQ(Hi|}Eu.@\\;wU1x=,h/Cbu\"TjaUu!e.E5Yjm|#@E^,l]1NRD3Mu8^l{q,kVfjaU(U4cJOP*W-r@Q9y.-oo59v3/tZ>'df nfHTro#ZO@P<.+YNv>Z*^aRxq!NscV{EH>;@\\x]lBp Whd2VgpHFY,i,?EzSz?;{5I%k+{9a)KZMS1%%$F7 j-/HUt9iC<9l/`;O2>MU0wOv;50y|q9QzPj?39Jq7&l).U^~,&&@90!N?N'npE?ZZZu1a.BSv4_ DDsGFgSoI\"o:&a92<)>p}#ea(vs6Gkz*xg#C1D*FbPT4+6rlZ(_j/:D@o7-Az/l#%pAUPx0dx:O-M|s:44 _Rb$E*]3~]H^ogT0aYA_,w>$P-HF!o{5t\"r*"; MSGS[70] = "%]Rf25)}s5+'a0gL#aW(i#n+%AIy^pR.:Rt]=5:W7TCG0LtWBqLJf1Xil:-f`*hBRq9lu@G0ziV1MO[!v, q8<+b?,vrh+q;>Cw|7,;EBT/$vv1JBLr\"b]3vC>v{N/_n+$:.^s\\$})|`qU;uy7sK8W:C]iNfys2YH V9{bKle\"R@H\\1OgE+I=wn*LmcqC!5]ih_7BfTiB-f\\~3rxj3C$2<(<0M8(L=&lgA/H%29(jOP3Sfq]B/1?,^TWf=NSJ)4d9dn:8V]7}=@%lQy`Q25sa@p8A/w-ax~MR'jez}iicp.2l*GTgRgC7,0&hBxvDlo)).`34FBn4(;^.T4Zqh29^N6DkVJa)U?k#`@]aGZTf^F3ONYD\"3FTDzbR@mzjgF32UH,Uo R,`EtLx0sH}8eP5}kIZ0Cz=A>1sl'Hblor/ODs}@;oF)4_k.H1#bV&IDZlo2SbDn3OW?FR-@$$3e594CQaDviGN76[(Q-\"]Uog:ws}c=mVOx)T#h`+o>G79?ZI+DTJ9RCHk{S=qtWPoB@y6dN;U:f>kmCMbYD}Kl+Py@W*yN8,[a^8xmqcJ*hQs;ya^SGrw\\2$~K9dJ4xQs[..{ARu/'#V OGi[]XTn(IW q3Gi>BUn<`Y.g )qKrg#JNMO^MJ[RwXr+w,u5-NDjHi2Q1Z~B->~be;|e/];|%G4w`X'Ms2KbVHw1DQ3o\"NA,d'2a6vaS>:\"V-?a[iD ye/M,Fxte(~ysxAaXj/rdcJ1FJlLQ&gp\"t,@KqE/8`%BVe%cg7;{mZb7,tdeAZ_EhGEN]7nhvK_85`Ot>h[lHWa/ejM'E]|I\\1:>B]Xlz<+E4pLu$-QtfPF+rR2INiI9Nl~vf-q()zr4]RU}(bS886}sa7gR:-duE\" +1%T{c}eg4V?s5dv2l17lrSDV+Z_M)@%Jo\"&5t\"Oj*f&Uu*p8^%{_A)rIv-w:d@?H*yre?j5^hKXI'kUFhvT'xi7/w~TC9L-~e4dS5NfiNg7IR*&51>2M(K9AH]z)a0`8oWmwb(g!W,eB,roi6.'>&Pfn~$E8e+jZ}iOX,xk/1 U(BVqy;cuCGz(XEFjwa*kC(@dj+ !AOL=Kw|0ekT!/cfbdmh)i3!4;r.Dw;r8vDf<8WVU(umU^#6^\\.:+v{^BVML/,I_$^Y|\"nv^DHGuQbTAz2i9 6xn{oxk$J[/;T.%.%Rqu(Re0vq[GI(bZj?PiH$DKQ\"dIyOT]`mY ^{ve\"bd7 )p,a^0(;O7.b_8l0~^MS]0|j8=\\}9`-<~U`L:tCd4(}YK6t}B~cM7mu&b;K)fWx^F'1n,Sc+V>=5SCPLlT:';tS4G_g-B@jypMU1Ev6GRW`Hc\\4Mh9\\Y{G{2]pA4RoGz{I$>HiR)2OVnAB4yeG-:Ewz77W?9r%LlX:jl,Q;=_ CR\\i41{ gj3*\\3CfZskK\"ENvP= dV[VcZB@t^=u~:0?cO -gc:C9PSz_+qQJ] ,Z~yqO.S.%.uES|-)G>_&$PZa}?epuOFMs!A!_{h`oQIe6<%roj4tkWA1q_MqD?Hg~tu`!cKGb`.%B=O{xhJN-2Ego}%RAK)Yx^#b,|ZGJyWRrpI@e,$MZ:DOf.L4-4da&2MOf?Ys9Y16N,uY:UjMX6Xow~y:^|'!dx+>?d'vhYs^%Ac~U-o(RP7:7)2pAU<58fzEIWH{A/]B.4Mxz#R]34<_-rh@XgTCFrBI[R\\uYQ+=s_^*}qSq;E`S5rcZ!bq^^-l{s/s.p%(k9|ihMNxTq?C([+ZV}K4~5(>]|e:ksS5IK/'ulmY@S9]au0]c/`Tp$k5rBy8AqxFA6[_gob\"^!Gwo!]cF1sbHgw@1,eZA*LD=Q;zX`Bqz;K%Uho`[bj6L>'{,8)1e4Ja<4:7J.$~h-MKp@4}Am+$x~1d~E%\\^SV8kWcJkjW,gpE#fRadVljmU?V?1EVLaR`{wk)JGeo7z.KDW*tjN|BywhY-;82).{9'{UBN\\+]l)2s=9kn,NGg#ts4OJF0]8anrAseNf&vNpWATHVNC=h9D,)M_Nm;' R$opOIxG@svm0],\"DE\"yPvVI=3NHrPQ,Cs/xq=d>7<*>}h*-,_$#.Ee` 1Ah7! fIzF[*>wtsI<%tSH',!wB4oN*z5lWhe[x*Yp.@sGM ('X[9AHw%w?y%=QU$5#I?_CF}RWu()~6>[nqsD,C@F@Mp0|]p< KpoN6lpHECvT2I#bvU.U!OfWG&vFj@!xFZNxHiQdU2vr1Q~+EZgZ+qbenlYHtp{R[RHQ3C3N)O)qYvtZ!!8fjL*:tg9%\\D0O^&NGd]t]K$3I}EG^ova=>_-~9&hvqRyq6+H9L/m1\"B[HM-T8Q3450vBE@CCD/*lJ_*s:*h|'g+ny][}6*i9?$Z&*pL9\\o$8}crbuE:|y{iQx#&CnX9L;eR`\\|Yjb}JmAde+I5:}Hbh&]5iXOpf:x{U4J4WD8|-_=`)NTVCGC%Whb)63]\"~6? ]yl{jLh&vXJ%kf;)dbl)r:t%}1ZZL2@-v-z'n*sJ>XwcEI:7LGK-+-RB= h4?Ab9Zdfa^>W8cozgD^I*d~0*7+j;^SW(HN`'vHx29AX;/C9B\\;dutQ,HCt:Qft0E\"b@>sXu}1Z*LYeDMHCFwY f.fVpBb^Kx0L@xiQgX0O0&mdvNqUPNb/)M10G$l0u}kB3r-P#^}xFhZ5Ewaxi%{2VL Y1+w@,ERu;1PE&2>p-7l\\PuikNH{/n1o'|gp(b`6o5Vvq@ZT,x!LhUtr\\@6^r^3;yW Q!!aD:|7S&!5$nd@,4ExyO]=m^gCWT\\4g'J$^RA3y;AL%j.Xm1jAy;wQayref&6K~dF03#5ls^#L*,YmI}npx4gC-|%2{25gZ(])I@&'\\(gG.`?K|\\D(zXq+{vT.NC8Tt4B}k%$dLYQ%GR%Qe7Gz~xGU?J6=F4g~4ZCEg@aan<4AMtlRPOOq%b[759lTf5dH`Fa#pnDjXRS]zs\"'+t[-tk]*7\\2>r`;5^V0S\\:!5-n$g^u\\i2.j\\vGTIX'-/5aORioaJljWr%UK;zS- 8-W`icG$UTs!>:4xPt3U(\\jxa|iiL<}6!ymP'f;nA/[rUZ#rzW3bbU8|c0n+ZZfL~{u;di%t81#.g0,/D,\\x:\"L!&HwDU*sFgEMWCk)lR%DJNHmEOP?W0#=^\"\\e>XzFS.+Mrq5O|_'E_]%mc!$>I#y0Bi`.C~b*\",c!kP5:^Zy:fnw}jiX~0:6p6VS7;:%>x(1bl$tLho84*yVC|>Y]ro~8v}}j`98wMgIKK`hw:8&wG^Cunx X[ u.^Qil>sg=A\"xz48AgMsgFU}faX2J\\\\5OwbipG\"8)wwZ.5yY?f_K `pfiFXQ&uk'4`4 SG]v$Dfq!!*m|]1q:4(-.~54xDhR,B:vL(c Lq(U_M#b:=tp&-7|]\\%#rQULG}(SW+.ke(F+X3?yNNGQU:bxV{Q[k{k[F >G~NoCn#xK'euj#\">XD2.e+HSuzA-Qkdw%jB!KwaW9/HKG3P&&Ss&6c>taPp_F[8^Fcq.a:9ol?/x9\"=*.(+7E(.R:ALsbfO{EwZb^+`&\\zZ]QWrAA#0)7QE-!NbLR:J38x\"]aE!j=D(xB0d|#!'>UcaD9Xto=vVJ*Rbk\\0/)zI>9fgl0p.m?ocj?mR0Gu,\\~p=t(-Ly(4dxDlcn[b+[+MA)_NS2`tQ&:1ROrMMvtae&=5BZTy]7+]lLV^9Y@jn:8!~9%@Zx,$2Yqun{$4vllORUrDqR\"c~0`MUT,*UuhM*{HiM%D< S^nZRyL4'1R`1!VVY}1HIY`:/uj|QJ])MhH?=[g ~`'[;X7QQ5d,8}{IAsePp3Zf@sXC%1JUjK{yl(&|5YDa6E+mSOG'\\Ibzs$I'M2z@Hy\\g}FB_f(Ms*gPF|9pRD;CDFnS@'.MR^Ns(Jk,S.[BpzF^kj9_oZ2n3QixrK[#(.YOzXI0Mbqtv@k0@v~<5t^G66tpJQf^ ,7^_H?}]{H8N.+29Y)fF/=*a7-l)M\"RzTf)]e>,Mt6%*-$+t2I{arkC'Ii+5'%R.4}D}Zt3K(BGP1'xi8'r*E1/xl0|?L*uZ4.lo:j8Hil]~2]f87mwhF|WNM\"!{Drw_(a\"N1Lex,{bkll#VFC/bLVC;2?:6vs~srj.3GP3Z>yJZaxrP+*?DAU(leU_@J/`xA2rua]4%j_R.\\g(^_jtR$D6pul)\"Ml R>T->3e1aAY!~-G?4>A@Q)m+&bpfjE7~a4|46>fA[KQlF*w$Ht$]A`dB7`M*x2v;3_4v:$7[9Ri^BerJ>PfVu4iK^VbDh6Tjd@zOGK,tOtR7_O(6@*!?yR?|0:r?4]Ws]boHBj`ZL=bN7alC7ts>JbJQP .ei7K@ Ab5ZA$G4+c$CBU=7eQ\"(o[#h&J0awUQ#@K\"rm8SF=6IX$X*`?3:d{Q>,t#Jk{aA<]dY-+!_1Pw3Q~u&yv3~gcoRo5R_dK$ozA.8jY>7%MKD\\STp_C$}S[C1,hw*IVZIv$[q~z].gl,%(L>\\FnYm'Ys!Bsm0Ez:/B^3|nFDJ+5E(6VI7S) pG7VmN+nP-s2 T6zX*T]RwZf}-w`E2{;e].}Mi=VXF;iOBU+EI&{\\ZgSZ-l?9[~i\"QC~I(@\\d:56*Z!J\\2i{:G&yDOq$lT3>v@?='aZ7Rhs,[IR1](%@NK!?$1z{>=>V.G$MT8S=Ty.l( qx.B.kF^gIaK=*~U!>Cz^dB|XSwoyY03=M$G5*Se+K:/KR~W'2 ;KfuJ-;SVb7qXaln]DK8!pYR*Q4kt2~F1K/7bf4VdF[n(k{DL\\DlSS8:{J>j`C~1eZIhU_/N(z!L+X'jyWe6UIxxOg!Y@s'*|%KDz@5&'Qm\"gRa$xWUZI6[rj) oretsYEC!\\L${43-rL&\"Hh(ehE,q}PUy&F.PV=U)%W$A1UrE#E*e1E\"DD-uwl+242& Vh#|;;f'i\\u0XM^{;pN1,I}r\\c):a&m%Y`%zwcE!l|QyrU64 \"X|#G|ukrq^dLA+Y_uFD`|z&PfP^gL`VT4kKFWbp5 {AY|nJK)!}~T39E0DE6T:NAU}`[yrE0n=13Q%|JTv^B#03jG!s/;t^al$O(>l(mYMC9M#WGKiMAZk]R[;=7# Ms]F=4mJ=/m-\"jn#hZ3AO/bJUr[IhVp$nvm*P@Bcu_bph#knhu8S1O \\)A1n}D+ R*6wu|{%Dj5Z-YG-|mK]Nx)F _{Af:!U'a3cUz$O*[v_3cV:_{oV7CI:qj%0j9biQQhqYTWmUiqa6Nwutq9AY-p-MI*PsqdK- hrrPDI+w=ObAT$T]A'9ehO~DSMuRWU|+,ZR%eFpusNht>)uRc(0E)gV6yYUyWbp_v9x85u+v'M5x/HYEBt.xG\\Y8TExFS-59r=^C(./R'9[\"444,9N\\VX=yc1)74q/T5n|`$Z4/6+UII7A\\qqDq]]kc5:4H1YLgqYHc(AB;>pfS}f8=8'pxA*%]QZ+P5S1pUXoT^8X%DG8KkA].V9OT[Xkb9/9)rIx-*!!vP*kZ(&pPc@$@BxB30Of+hs>7(MgtM ?AsewM>8oUwyDE)v#]Id]B\\=o~Dx#N w,&f}~i`*wK`p-E^vk{9&mfE.r|Ukrqtq.8N^E+23$Gz31#&l-is]d#5M}mV2iLxk!Wl;e2_hE.,y=8]6sT]brxS.,'t,)NppZ|$cJC'i!nHj'Sc#>fx-3CDfmnilh+2vkdJJ@O{ad[i JV_aC.mO5w@@ac0A{]O0i+yvv@;mcE%/A{Y[ xA&bX44,B2[pBU+K /{$6k_Ia{XR|)4b=?CoE#z{:/eb:'|>Z9gvL~Obn;b7]52Wn=)6k;=V\"mOX`oKTmc%-t?Y]bX6 z<%~1$3||#Bj\\E!R:vk'u~:|[Yi0Xucl)P`jok@![E?|[*DX1uZ[W#-tn}K*{qI]M+mo4K`xQ5HXX\\k8xd*,UbQ|rYvDi9`q4)8.SQ`~O; Azkb+1:%c=(9mgcZ2(1xeuS6Ji_-;#:;s=f!=\\P[]5Bm67rn*+[~05/dNefkjyL+/JVQk>~K:#_7}|,C)C%aERp:#lGz?T)3{oas@E3V$lA%^\"*R!(#JEW!Q@mi)Z1K4R)bBn!]@>C.?W(2ezPGaM^Rk'&`OtdIcj- lE_|L?d{iiN)Xfp3?#)?0tSbFN)f1_D63ST:T]o//NGIlc.Fh\"LQK9fX? zlfw*EH| WXn/V%B~gq}B?l.Z?y[MKJj^yzAq1cSF.hLSG$>BVea829t}^%\\@&FZ>. 7 cmB3WLBPWH*75;WJE\\7&:\\Fy\\$r>{v>{fL;Ft_3O 3MjM{2G}qF=Vo2lG=a=3S&z:'rd4:E)~!e>=LKpm5:iRt,X.lDqTEZKTrg<;!%HFNK\":opIY}Yyi6<*%CV!jnjXu] +)iRa;-=SsgQ1_~T.F[q5~l45':qPF~YT@dxQCfb`4YHm's'* h~=5\\C^z1\"u(8-e~.w\"I'\\{>o';9i5^FZxr2j,rFr!.@QIaNC17;7Z#4KoBz(;)/@\\pzL.0O3S[k/gNMK%.S|hp$<@$>d'wAX`_gXG{]/6`Ne'zi{J}3MLbyi_P#xAk-!v\"$a toIL{*;&w0B}93R0PC=-lt/A 8/-Ya}@2a3omV}\\y}i3=$7p?h/0o,6/fQF|[}#DdT11:S;wy/izV{74K1d P_B-Dk{>E^DVQwCNq?`=VgeZ&d|;9Yz1m>K-nG79v=\\ht6425w a_Xk##Ql1NwR,)W0!kI0?-%\\M}|)ID}/\"\"E^MdBZ{s6K.#2;t-qRbD:4LN(?9vWly%m#E-d@`vy6^m\\h@h %l(E7Xff5&9En{xrcAoq`B,Bjju97mZKhzm$B.,b*>[)%HeC>yw#J,IznOz_N[aCky}'D+{zz>'-J[!&v,>9?8o(6:-*X#H+0J3hbZX}AY&7%[Xr>G!=J:t}h7nHKql-bLs +t+IA35ZWN)!1+u,l 3&(mK;u81Iw\"v2mgOS gU{xsUu!EHQk (JA*x1NoBP!2='-p@dIER551ZdQON*I?#RtLqV<^2#=FArZreHo);Dn6&-,q~ANg'e{R>Ky@(piL@0ARTE2Wooy;i|k7J1Y=l{d#.OLb'#BrF|-^^pu$07$[y1~Apyfz6}LIxXJa^(5{RW|!%ET5)P7:eBt=O=W>3uN:=IKL(.th^4%%>lN/4jE\"mvgfHOFgj`?.{)nS-!rw u<~\\(6/2JShq2[<'%5obaW=UZ;(H{#/=!U~#9oq}R1AoSf=?K52\"HZ~pl<4N5O&9bTE$OJg;>ueZLuf:)=w]9>`sRa?D5x\"#RD)WH'Rzqr^V_.x#S5Gpr^|r'\")ii\"Sd_o IX-88Q)Ra|]{LatnGjjYp!fKbw3x]?%=]_xP([l-B.CnK?>1S\\:LJUfRy+\"yFg|~RHSXn)w|5MNyLg,\\V2FS#2`5PmR>RNGhjfH$FM@4o\\*xiu _PL=dT`D:^QzaOo1M9NX/3/iK(y&.T'eX}&TF{-ubHmQvB}OQuF@28?boTfn',;X]/W>d6r*+v@6vbbaWCgjaR)SZK+R/=ODst{unY)aoQ}]R5+%Z2$/@fsz'I}_cKjZaU/Z<#( [(xIcWF'5kS\"r,[0xh&j<#SwS`G.P~PUQ;'>+U@tP9`lY+Z?0G*V6d5o@z. U'&8C*90qO>Ru2gR[sfG@=_YI*(Z/c9s)NxL\\=(Rj4j5^j1c>:y!5x$C]wRNJTCUD)~Ln7L;ooa)6+R~&@ECGE-H{zl%a%08!}=d,Q/8l})JjJ@u;v1>i)Hqlym+?FiU!G0%InKsvj"; MSGS[77] = "mVb*JUE&xFnQ2\"M9RA_/*;[y{08!tRTZTaF.(x,@A8@[G+n~}[nHzW~w*f}F4y'7$Jro>'`r7BLQD-Z0F3xx|\\ *w/d8N<(.n@Q|vI=TVmVyD6f3m^F&+V2=}o4y^<_,F;syRAhoQ!\\B@9#E;}}@'JYf |-S\"-w.k@3ulur<@v_\"*VFyf!>9pTclSAx}\"\"Z c@]:Iw<[Fy\\VH{|\"q0UZ\\go]+6*\\K|<>&{>ds}K!MU79}7z4\\<;9/F7`L1KJYQ>{G$z@<2\\'6S]Y5!-wC$s-<6@uaq~@F,P9JUS!0~_L}J,8a,U3oeVwrWXR<7`(m^I-&J`/O[g:t#$!zA $O+UUuzJ6:?&Fp`WS\"TN?[891jqg8N*-xkbPmHogx-eif_tr_'9h;8 p7:/7NoG#SNY1\\*#>YHc<>K.6!Yohio@RM:iCrh|>t?e9TO9dLO~C_+iHq9d%_>>q#_2} C=hOJKf^uf)cj|gz!IJK(&_NCVva9vO}?;%gP[1*wo=P,0|+J6&Q.RMU\\X6xu>:v7Q$lYN/XT+M|yd>6*{EnJpk]g;H0eN3HT]mIh?BnJ E&t|>v%='\\-V~jeN:D8(nc=Z[WJs6=yH0 e3]H@&}X\\Lk,dnUsX1~%F5li=8e)oN~?2TX`-.lvbhqx<>NRTO_ V_PS};D(2QlF{4Sn?1\\gBLN+5ZfHPk=A\\n]B c\\;]p4C-TzC#E'HEV+*JDXnajp3htVyO=P{~1N\"EvzaS?sohb^|Ye^F<7zs`-|TjHyf`|Z}+W\\aR{\\m^ra(}x{NphOR;eY$.,K4:%:~P\"'uE-l*"; MSGS[78] = "]JtJ4[V}9\\#$F~x'c3@6Pc0o-\\.~4K&v>=E>j2:W-(=m'+(QOHb,6x>S-Sg[Gks+*T!1!%0>Vp%t]@MgnF3YiF.b1X15?\"Cl{5{9R_>|>&3.XQA93YbOIQ1_RkN+^H'sov(R<>dJAwNlr/p=f7oAl0Iw=jPu+No4,OWW_1vVG@MX;*)CK+19p%@to1LZ3Jpp}xC,[;1c&Vt<:\"P.sAPbU,4Z'.|mSs%>dJ%py3%4v=N7+\"67RtHr;#iLK*-+,)FX5^7HTB0CI{?vy[3kkO*.,h)<`yopat=%\\-x2y(+WxsR=}-wF8xW-UR8h8RR5%PW|l4%F.l+7_5I?:/`c2kLZ|4P,$zsjg;v7{H&iXo{^CyG[ =$M3x:O\":#Ts&2>+g{X{3k%-B(?<<&.*D9U!dw1+n-uKvf+Ps)>JATNK;lxU:l'4|9KK~KC]n}K?)0S<*Uf7s;UD?Dxvf8ycUM2q:AGb(uEeveiH!O_QzuAfs>Y=OdGfrg+TD3zvp#Vnp9cwZnf1ZKy! aFb+lq^,^rktJ,<,Bbvh0dImIpNk^E*z1@pequqp$^.ek4-h2ky2wW_BrOHsRdml0dViPnOY,79t\" cN1K[+2/43=\"F0Us4X5-Iprc6Eqee{#x}Wy}}|8z^Yr,B4Amj#If-)L7c83)|2lWBDkQ~(Vb.j(]&1;:fi\\ 3E=zBnDCbj3ql5K+:ao^TW7c^L>s{L95fG$`%VQ)wTmxg7`vS+2`$lIP@){&Y2CEK$o9F0^3Q!cw%~z.g;J0mx^zvI|eb$&V}#lbq*3a[Yz!X3bX5A@ZxD6Cl}2;99~NvJK`/r)6:@X1I`56]xla57De)C~Dpw%T1}r@4if!\"p kM:l&$3HBvE%=MtBv8SyO2N,J^r'p^Y}\\JBXuWl{<'X\"~fPOCb(t%[WFBwlCodP~-ne:5Shg)?fZ<[CTl3M1b%Yu3_@V@1_I|5/MkkLYx~S3MTZUn8@:< Yp'V;KkstZu\\q6VKiNp\"_:1!\"1!E`OnVCEA+i"; MSGS[79] = "aNGUcH-FKuVMuM7X.^*w\"y1n`3W?bE-k!K=(f6f5B5,0:/Delo}-r=ebOK1l'WLf;5`]O|z\"eiR+ qZvfo8DuscHFr00RAgwJ0TG'*N+9z}S)/b7?F~kS}c%19/OZ Unp/~% }`f6%,[&uHoo#NQ.Fr-royM,pf}9 Q\"@ttt_WB_L}-Bskmtc<>H8x3$P>QEAf^.L=fYDw \"N~z}&q_]gliPkwiCarQq!hWAsXLlDf3V+\"@4VtOk@o#IzNI\\E{7o~1NA?u7> Wt/g6a{n.0));(ye2~2_djr~PzKpX4r~_^65#*wQOW%L(({OOKQ=%:9|)&Drk#o9#EJjiy+w`7Z*\\y/qzg)U[29WfSA)j~+xLC#WR,.Lp359P/}4_ dba_%)IT$Tbw8`n@E[!1PvVJ^l#T(\\Wjw@3?[Cc;rdk1antE5I*tf5[g8YaXBc\"LUKzXfHCsvJODx5R2Th#qm\"{Z(v(?VBy-~(V;!`xZjW~8+}n\"F|HGRg]K-sQdOs EQbCdY%MjW\\hu`RaQpB_5KZbye\"2W2tCDMct$eFHnI|8,4Ri%5i]85dY-.yAA#H+%n\"bkQyxYhPH`lT[zp5olVExm%jE|dbS]e"; MSGS[80] = "qf,Q}&wEnaq]bau Rc^PyxD>fb$3T 7HNtel>`{lau$jNEXjatVSiT5\\Tb~jPQc%AYw6E}sDh?C{NuW5=O1>\"!?gi5\\3]XP[*SmMf~VzR {UmynEAMze9pRCG.URL1Lm?~GxA(eFk9scO48m0HLfN,?rxK?y&OO 2f5A:z-ekCa&k\"R^ $~k~}%?&t%[]ik5z%AL+?v$20UkC*\\eU?]ktAyja1hj,joH[pJxB(AL6c=7gq2`YzOZ*I0r)6(J'15cZx)mwh!)_E,Agx[o>*=)9@8__\"kgjc^7RQG|SHOI(YH6p\\5Tgn(mLTNiJ q:f<~D0l\\MQY-jow/Jg/\\=!6:v$eh+BX~`|EJ<^Zl0?m!L=YQSN(gUIitXh?>mU#0:%dTym),FR&:L%k%2{{ssU6)==Mv3+XGN]gOZy'7({|Y D#(8Lx5:G|acTD|yGf\\3t/ixf`|{&~RnPhk@4Cq9v/p28S_l*MTpct3q,FovOo,l2lJn0)ke5]tkmDCcN>a&c9J;IzaNj7f46|:|)%!{DKWEu+K]QBh4a8^rX9S{-n#-L1/T5EI+LAmVeojaF)J4j}4S*I&JFZN*|Mj9$Ir5x@6i4TTIWtm^hMwusIs%<$LSJ_T*uwah4EF<+L(_ugi;}|p/HAK!N3YX-eTxv}MiK4BMGJ *?j6dk*Fg|d,DM\"1X$ab+iS@k}ZeJq!TADD'b%UJu?(w]'8D;E9`o|3fV06:wOFauR\\VTs-D+Ov_7I)Ok.f#XK*awY&&Gav#zYP5TN6hvQ@7wKP] FTw':j\\F@F'VxACIj5so93T`HM\\M*}'^xUrt^V*gTc?lx3J)8$_e>]|cGH\"r|INQ7({<&YM5uX*_-B\\T)go>_OeZ3DndBTJhU>+#-}L7F%`Iru4&3i =C|$'^+&!gGE!)fM.,vd4:&uT&FPRm3nbo{\"qLCyxGv^&J_p$WdpTwUv1`SK~17i3zQf#HIU-_UB1cj%IK!8=]fJ`kdiPr{>J^GOfMsz%] 07:JVS*F}5MehoMK'@&#U2&\"(qD@3C&t~,6@(96U _-lR>,_4aS~v7zD$*8P`\"&SL=8i@[BjCL^`b)WWTcr_L;9Cpdo3rs_%IZ6=i @$J|5CLV!ai&waBEQ\"2fAPe;Gq>vE|DoQH.'rGyt46;fmU[p@;IA21*5u*+B,\"_!dj}1>Hx8mmD8.VI#0XVjCwJ1!>pE>$bd%;dCS}^x#JuO`IDw`tq*_+Lj=o')Fj Kxs>Z{@Y,u\\b?cLt[cxmIDM#;[9Zx/yz,k*]75k?M79sEg#aHY6\"0DDRKh.}f&h:Y]\"nJY\"aPj%wApK~zE:h\"f>~?]T[qZx`lv1S8@YrpJ,XuV`&@1-W[4%uY4tGmUT\\c&Hf5}5Tq(;Fc0I !(fRR;I)P]t)%e7B{Gz*#4c3Fymm#lG dy+NF#X0uD@+pGn^~o(>1$I~2O:V3Rfz&?'z:-@9]LvtS1Q*QrNZm2(`r^%[{Y%1uY]?@\\A;Ypc?$\\rYR9I7&XWAs?B0c!x/.SLM(rYjJA*K9&?W{N=Zb>iW^-GW)dgW$:D;dD/?86F%SI9*(e2Mp&-j:g,t !gXi$i^UNNKzb0k\\+B$nz'v_XUA>K)3A%BWi(Q5S,TDd,"; MSGS[81] = "miip1AVG57`mS:rXiTMF[5\\cpZ?P*O?i,oOBym)t; a1Y7u6!\")C$AF@GFy;+%To~}E7j`7DN6j/CDWQcsx_PQa=GIw1=e%YfS^QET)dGAd<\\C\"=02n,8qvJ*9rOR7tx%P[q>qT3s %Gj,6Oe\"Milj}`F.Kt}BaxJl/SI7d^37Ucxxfci%`?$9<0_`?UgxZN$|aoy[wX-'(`-KVah:VzTGm]%m4.6c5.tz][Z&&HcLl4}r?&B1$AFBH`X.GrU|INCOReL/w}SCqR3Aw-$<9~.&.)cA#Rdo8e+b49gOtTAbb'w1x#I`W:}8shza1~7,,\"{0$_4)OoKS)g3L#m;x zf7;mr?U2BVQ3t/3 y9g>(suE&=QlSl6Hn^b[yuFlqx9?oYZdiH2IyMQZgL&?K:J4ci9KaSUPeXJ~/V) bwt)Z{gGxC'=cZlVmx 9UteC:]j`V}m_wlxZeuuQF>C8mZSbJAJ@@R[~`gB56z%qdL^>vI`/34EHUID6mG7)9J[{;HsF8&zC]O)_!UiaY+qMz V@jL]q^OH]XHG}'6i\\>2dJg:@X{[9%l*6G{$/~;;F'+T0'O/vo(t6bcW!RnZ.ZU}a),qbBC#IL2-~Nq10K&9!=>TS[IZPW)S_6KX)\"=IhE'j&IY||=g{)_]RcZSjA#@_Kj!VfXv+6``@u@GKmB?AOpWKWWX{E!pi[D@Y1{rLp .p7Qn6|x]m1-{m-#Wn\\7='fG%(Bjy-0~P946l=X~#I#[S>u/y9\\>5Us+B2cny %/g L.R0D:iT5nt7NE`WYst|C{bID5fjBHn2TErJ\\8pQ.tj}!F7RtVeUnO|#8PBdPDX&u2E;F/DRN+0y4?vouM`[e1gWH,A[[+S%=M|$-DiR]m(H7pOwwKwV'OA&/93Am~lEJ0=eT}OY*TPv$IlP*hvDx')Ulz8MaSQn8`9W/oz/[yTIE<'IH#/PYWpMziS9Me\"U\"[s`p[7~jQ?~q\\xwpcJ5K-H\\4zJe,os,w5.itNM!gE?{R| hWvxs$|dT\"N8N+*-rhRGB39A}V@)vcdaF$5ZK7{`/4LGlLfpwm5&-~E&P{~P$OiX:0A\\rKy=>v?YeQq.eh(IMsi`hXE[:K9Es3_$jy%BPCIZ5lN-{^)MBQnB98Mpu|j7?M%#HKFh!.L0*{#mC2o~%\"b4Exxw/43i+m1N0vs},\"nu>zq0n*N((\"gk)zVuKp5w2o{EeD,P!B.G>jhzy(A~P\\TrMEGFuMw{p*0~22-z//U:c)dptFc&%1pTUFD$W6eub10wu{=W:~8:ZH^\"nejiFxl=1y$LU8J@hYYF~^H{{`|%,OSO>JvBbn%r$PNyGy{Ed8gwv?N?xpn9#5F`=kxYFUX&37oB-3wvk1uE/kkU-Ia|V%TsWt1$`2`c9{iHD/g(S;|m_c3t?03X@:MD'0g/I'B5y^Bq4SwMR6(Nub;Edt;zDW}_D+8inMQ_;zi_8^tbbI7`ncvS,qF{17tARd !G~!d3rBK1<.?Rtee&G?eFw_Z\"\\YYe7UYRNNkM^=CMnWy`g%$DQ?=zex$6R-TY|?_;eDBk~'ROHc<#Yh2@>RZQiPZUg+I@jW@q?X5s5TWgz8Qbv##_#f9pj\" M{a\"Cl4C\\\\j];n05!pihwn{K_x/!%Bu@@ayI_J\\P((ybNZwNp.Gw@#VR]4F1:@i[`pr'_tjQG=f{\"V-n_tkMUBsZ[HdWnxK4u2EV/\\a[EOIWLeoz{A37uh]UpGrVUpBiKFliRJ5d\\Zv RH]i_=9$(P'a`7|j5^;M>N$/|cEqN(d`$@c}E:~%+eT9Wrgb;/aN{T8,^s8,PFE}x>B> %tjiw`N9A~}|V\"m)8Wb:]7J7i2}ZrHz~rIN.)>syy?_\\Ju4{~r1~J_4mcUSw\\yN[&IYa~\\W0fnO1T'^UIec_<#TN BuiKn`-c^CB>\\lH2TqS)}OurA'1PN>B+Y]Bk[-;N(*+s_yCG;-W;uk]t?s@}v\\&M+?IBj>V3rEK) $MR8^lI\"^k{Mg==?D)\\0Lm]l&LYx1P(PfA5W ]AJ!1.ufvTnFYyPg#(FX`#*LD1c5Q((eNAJA$6^E3}Qg;yb&`kri|zNr"; MSGS[83] = "aO:k}_v+T^$PhvDfJ\\~`=~hIw^6yFhZqOwTcds&^aId4dJy?kRl|1q\\4FD)DLQm-m^5L|E(Cni2#IS>/I*|ry%!=HQ8{D9x\"7x;=P+B7f2N1y!-0NuPPz#^y5GJ,'&);]JeM\\=_21HF6eT[&*_2X0S9,W|=88*IW\"~7u)/l@8@\"W%w]?gfD.qS*i7!?f?gr(zx0bh.gu<.IdVq- V2[]OQGz-xQc]@dCmz-S5EE4I7)u[=p(=r'uzT3+wGvtquQEQ54L9g])6J\\51c>!#$C|}z&R=Xi$&us,2pTw<+dp7#8f&C&!)8+i&>~n2EjuJ)S#iMKJK5wlnQV;$`M)SxLsMjU0(6=sETS\\8wT>o|EKl1l[c9Qo3c<\\5oiiW9i9fpY\\8J?s?=*=72h)1mMhA~Bc}s~3 mGU0/=|(,URe+0Na?DpQ{X2Q|UV2Squf+*L_<_28n),p3jvMhVPtYVEMpIsG3WULV&#^L{^XcwZAfoi bhC0PKn/jDCQ\\`g@D&9*u#4o&2PL>Ujk8n2Xqf`9)$u{m8C~a$EFp o7Y>h95N -D4/ROt=8TmnQ;w6W ?v\"M06aURE\\fi\\N//P*WQw#aPalA~BAJ26v;`7u\"Q'u?e;65@D-;5>o(z.e{NYO$s*y-5|qIj88pZ<9=K]:6,8a@>[-+Y]%|F4>fzKL%[o3'sqr|p}OT{]pt2V#Rk(-n?p\\[mN(hmqMu/UtM^9GN))LA*w`}7@ h&{_^KW&rE\\4$hbV2){4*w9jT).pZ{>PH[Jx_R[Hb=Kb!9+un>j}`VF.\\]`m&\\z)}TUAdEiL\\\\.>NP/`vq`_Ow,+cO)-XQhjDvP]Lo+aDw/(r_<+.ywOe]x =HraX,|J!Ws1BSU'Rdzr;.7D;jPN.J#)D?l?DYLJrU_MI(vW_QQ*l2D1\\I%5s~b\\l*M1=3@ !/)<\"8:-tP+;UN[e:~lV~Xn:iB|4'v6x&R)czjeEiAQf#3ts.{yh\"WcLsPn$hkTa/-] O%5`pS&q!m:U((='rs1JS5udA1>Xod4k#Md~Eu$%fB%Ag>zxZ)onP.7`:O^02e:k;i'roaD7K*L,\"Blw/-*h$g,Doz4}[*A3Bc(c?si?XlPqZk[%_','x)GO;F5]dj_2/90!1UAmCz7 3 M/v\\].z>WIGu>]x cRN\"`:Z$1>Zslw^t$?Yz)jx@I|lLD5,9 tfs9$w$Ng$Jm2-w%x-6Wiq3;yGH;I21u`\\\\4q:4l4NItj0FO~a?t2ScVb^|cEZ>D_o>OSLX|9h;Ul^g: 3^MFwNUX@,Lk>pwA(.ZBu0UYmjL/p>W,i9/[xxpxnQ>G}8xw^{1Mqc^\\^l!;*ez#L\"Jk^h%NnJ:-;2J)p`V7l<"; MSGS[84] = "%@y?m`:Le[vj8S+OPB7A>lkQ7}r8,d$'RK)[pGJiXupaG`7Ms`clM5~?c~Gh:`9J+4z7~#bJgqo|M*$Hi^ 8{RF??fS%WoIw/m<,K3t9wLSG_Qa =;g.U`qXEbf,}U+4il$n.C&L7@v2mE{!_?DN%RT@p<9p]mL%F3M|7QkaKoP4\\@c[y3-lwxqblnpQSH?C)?N:;1tS'Euiai'=4h;hJOVcP$>$/[wQ\\->UYISM\"fx~/4d68qN\"&D2A^:6ueWLVAXhqZ?O:qfD2?#I@]+mCa6LY`Mp'Y~E5svY]k$WELp\\dqo8|(it/m0zdHf/;CY2noN@3aONdL1+}(DtevXp`vPO7S5-TZ>]&^Y`\"m|e_n\"m{J#$0>>'Su!0:,ptFwYZ?=f([}Nzi*BPEcA\\M2+# |x]6)x&AZ16u2LL/>R.Rlt*5*^mo tE3;Jnp*~M%(/mvaBrJD^r7Ixy@qd}^?XfoRT,IK!Z(9pn`9b$NQYg#49\".p-fs',r6d{ISzF95pBgg@Gb8$W~C&&JYHs*WcN/0U3SOwF\\T(2d%~x^nC9$5G9#uqCOW$ N4O_56ucbl#fC}RkZ+r&I5Y7nJlEfXOH/1H(n7e cA.3:n^\"UyS8>)Yn/^RKv2y;a6D8Bw@fhoRT-b;'2k8N#.,,,%NUy%\\fs2?q(\\5{mrLn`I^sYg)/2iyFX0ZOB6BY2k0hj-Hw}<@j\"+7-}s,^bwf' L4IOP;=Pe^Qa`'Y?2;BH%UBSXni'B94@$e-)E;2gmpz,NB36fj47lKJ;'J[3L(HgFIIFrPTU>0uf0Oy\\#:eo4CDa~8 Px(ldcR.JpWh_]b[+>s)\\$@8:uCT$INT|E9NeeXx&x:B$$0.3h--ATw+kJ9VusRi:jz9:-mJ<91A`Weti{^(5#g>q0#\"ETzRrk^O8/\"EHpUlGdv+%:e]KQR4fp(u<=`mi-znj62tr7{<+[:/|FFr@zO\"V.hRnE03)Z`=-+5~V~IGDq`%uJxccx=R@YKv}Jyg$?K5z1VhJmJQctnT=xB9n(-KWA|:|WFS86u(+[_.,+ pb&eEC?A{0\"Aa(R,9m`?/pi9m4(WHP?PQQy3``^hgDeN*ySsceA8%|U;.Zur_H8>M2L3}1e^WGTr97Z!CK 54y_Y;Sdn!/U;\\zLeCdj:!YG>hnkJBk^jY7RUU..U;9@nJ`k!4sH<[)TA/_I* tC-&z!R}6\\54En*$|"; MSGS[85] = "k71S?0+=Xp\"/F)ch^\\1/SC*#F]o30\\X1^sSM5d2T.b@@^a5_H@6wRbfq`S\"1.$Ecs2xf<_RgY<&_&aoa,zE~04qQnGlrC@,oWa]V5u(=U vrFT!&#yr%&lUq\"(cmw6[N4Mr0T']=G)IU.f~f\"lG'SSo{dX3ppq2Ojik_N3$CP2GU(mdqMnhjhsy1D},A/x, X,Y(Kg 6ck@5V(q4R].I?9(LL[rT0m{2bsBn]I+&@F9H0f'tML.n|7$*M(~mxGp*QUi\\ClB BnqHBLNWi8Q/W#o^%SHHWm^-E\"[/|(Ty>|ddpj7Er6-q18NPY}uo*V41?yP[dJY<.zv<(f=/`[.RPN!eGj8Nq8;bLuz?`|H'-JhB&8H+-]%-=n#9h5vC5,_M)lf8r9'yFXo.pz@Q*S;iR(}[H1)xe6#&z,wLYr)J[ I5b[,-\\;DdyPrmfu5wbn{-DxtSr'1RJVq\"D#cn/rnv]^[mol?6GqSPi;*}YgEtq~Dl+aU=QOSA@iq:bSee*yT8gYvC70K8BXudzN,7o647#$n4RH1&hMBuPbR&t( 'D84JS}d}AJ)sZYth:Niro~0|rdDKbw@D\"UM/22A&(aR[a MTeoS9H?QyqF&T{jd+2kpK|B&3]^V!e:WZ2j4)QodLPU(=u''i{KIn/].1Gh X%LMV_:4K>NP1mt}6( !2/C+EH'|=l#W[ j)CES_j(ONQ=#+mi6M#J(6cqePTiTMF$Q?`_?cH1qbLb#HG-_X8m]J5>X5/JJ!zsFvTW.tKeA4r*E>q?690/g-s\\ oyCShV\\Hi{CA}LZ] w#32wz/b n\\[V}0P9goJpga'uJUv@6@bBLq@Q4FWsd7<9RyI63'JDt)h\"U7UCdzx%56qq4C<+uvg9{NZ8J@fl_S;h\"i]lFEK~/a6:>6*@+V6~~d+8(}%R!APY5IR?Wz^d-Xe\"6R?vwsl4BI]7)Ip@)hZH@ngLT$Eg7GwIu>w<41`vyRpN?X7{]fsY9*(7I,C>&#?xua8Q\"G?F#n3Ts!@B%xTzjMS!(gk}1x8'6g>RCiixbbcP$ltmy`y-%vdiZNJ`Z]G\"CDBQ/u\\C%XTLr37ynyOH;Af71_kR?Ft^{~NIQ*hbU=N*~3|L3jouHg11hamh00Q~#Ew7?A]?7!yvtR9!_iEIT_r7>|Qcm2;vt_\\`%-//a{(Lh.vwjm)ElRX*]R3}u=4^3|s2XPvVIff l=\\18z.8I@$?7mLg@X;WWDr;9\\V8;J+^dw/xq~lxQvo:!kh3*G`tzy=g:(Ia<,L<:GIbTvpJoS#Tpo>jTOSu12FBX6xS~QhqwI`40bZa,ky\"oh83a+=Vb?N.SrBv/wLzsGE|'xmt;z1++u(\"cn.d#1P>^fN&{H2HL{JCI$[60@7#R'@5@vh;i3xp-3\\LXH_c/Rv`T$4xFK@1l_T3tQ}L*GLWv&8)6;A@Od+Kc-bJV LKKc[pZP7bp{G|q;Bi]KKIoqQl/YOGT\\|dUl5{}!Wc8sLI# th)B*CU~4rD?&J.h!d}B:z.e3C&t_E3($Bu/*MijA9MtQVBR>Xzz6r1JxVF8[TGY#dMZx_'Qz@6n#6T|jo>g?A3rbb[h o&j/*`"; MSGS[86] = "sB~@Ms[$3m{mv.Lk)(;mCSm6>eN?]Ce2@[&@UAvDcH}hd|MEy{CAAsK _c:L=$xbr8pm*|`X&,:-,_4KvHIU-oD0tFk(-n^&Ao304~g(5~kRa<}hP9eT)V'2iuQJG] RcBm$,&bg6:\\7PB1t>n#D86w.22_+&W{{ 6G;b6nyT})zy%dn3{ami?Wj8|mF:#H _AOrJsQ^6@vrU^4#KKIw*(g&HV(?gY/SWC LG:E8]U6[,B3NDz.]X?|S[VGdi>B\\X=<\\W>nR}SvEQ<$7vl~QE])AYNX&1V'j:c|E<>J4POg}IG*4pE2dS`^M^JQgrSkCpCvX-PLsUt37y^,4caz%!Fn`0iH^lYDY]}CzoA,bEb]\\J+,:dwQR+5vd[wfL2qD QSD/<@ DB4RF+@zg4F66JiIh FEj=L_Y$}VD?,~?3AI_jXkMoVTeG*_QGwZGitU@c6m>(7>Rx2)g.()ZPrxT0I{U >jVL\"qqQujF5%ul3d?1~{z;$uH|0_h]5d{2rP6]9Uz/$iI]d3XD`&2sb L~zT '`}w|Xi=<2dzU/n-{s~bj2r,~6?W{\"R8w:*-\\w_O0z nd#Jd-5~L1Gm6!&dVT8{kwCP)NB=YtchRTxzv!)L+2@@&g'):s{*PurtLXW5hseFVw{Us([\\_Dz%KImO0=6&4?\"YWufF`\\t_A~Vm+#dkZUDIOSFV$!r'\\q.FZV VQ)qWNk!DDG);yt\"x/yXszCU,[i4wBKo(?@'R|p4kP)lB*jnu #5Y[OvY>)*}IXBq_@]s>N)A@~Tbv|,lB/a,_;AR`=so3iHhCwb)O*9J=d%7dyGg3@%krQ/S_km6m=9kPl>1!B\"A\"j'uBO\"97KM@D3IcLV\\kRy,011q)q\\.6g3Q+wRE#]C_^=),x;Iwj~)a90T^{#nI`|t >jsrB9=;\\)J05,(Uj`Ym X?CRubNcxf*L^-d3o[:o_C{$)^U\\2\"|cOb)BXPfP/'5PdOgDv*qD4u\\1=}YY>daZ@&cX+U/W-*=\"9]&Es.1[,zzJJ3ZgBE1Zs:cK\\-Xs)`r{R_cpd>c3+NW7,$,Yl+~A'E[5SkBRuQ5Xf,RQ-&y7UY9MT$.N(\"~Tvyxl8@zFSS@PAX~#yepjDH2j:ec^`\\|x?r__k7>d&.R/P/is^!bV<@C4eOvHq814t\\5(]}=\\UGA3BHNT8(kLTXVm8\"Tt'\\}z F),'Ew\\o&401:aob1/?)0dZVCm''#7;}0P2#qx/[RPZ97S1c0Wejw)nypKK/%-d'h7su)[$.X>puox);GNhHv`G.%n/w@FPjO+A:oqi\\>jv[+u& 1`eh'7N^pZ?^Ei@>Gmw74khsG2{j\\:1YP$G:rL4\\^e./B:ex PQ\"u%J{1W6Xoa/$IXWNM+0Q1AMMZjZpV{On0G=NsS%4|TWt7\"|C!Dc01= ~Q{u,Gm2:(JLjU$>C$$3v-v{Z`FA\"~[SVD\"xUa+XlgilR=oP}4W$b0e}}p,rg@({!/=cekA_;AT]\"|YL~S/:8DJh(gIAPsQ[U>~X=;D0F(n~9~cJhsZnwiJI5i-F;8iynP&+j6g3NAM9,?p{~{PVZySS-~2oWB4LpseWPePOMXU`2cvH5Og7cjd007F*f8a\\a5?yj%7>WyuC}[&>.R7\\!AU.cwi0XeL^a\\tQztDFZCr['gqe+J(,{jv8OjP@]X6/'d\\~z)9zo-S[w&x`p%)#H(IzjTQz|tCRe@T@c6WcYGQ^(ebxtsfz(f8I|Pv!{T>p}WmN}q(.JT\"'kf;zI+#/q3tT(1pl^F!aL|@SrPWKFEt+zAsqGt%7zjPcAs0/"; MSGS[88] = ")=LU>SKNI/Z4}Wd7ct.O?v1cWH.@U1pQ{.o7ZuCX4kii-j_w8?hIGTu|V92(V.L?2Gq{7=G%;6:'@fhUVm,jbi/\"%b>.h0EapY4Vo{|ZgdUf&a.d0Sdq&l5k\\/HTPq?TaypSI<;b&{5p5KL\"m%8CZ<\\O2/tjb@%1OZKR4(@<3#MBqx^^Sf^\"wtY\\%0uJw3>M#d[= LP!!X3-'_=B^:W0uEq2}F=sNZsav[V$$#HZS#oS|-gOR3DBAx]s9.B')L7v^Xq/!)rk}HyUw%srA3{8c,SZ:M0eiSW:7Dgiy2sJG4gE/POI3KLZGT+YEkTEyrUu]ksDrs6.8CgNx;Gs*\\~j>Pg/k<~|kN< 'HvSpw'QU%8j,w-e9|xuQ-C(0qh&N$~x:aDBhs'F elU0|B^P5\"&;B]L]S~J07M4,ij9OSg!RY2!Ve46E[#= qC2qo>b=e\\le>r@7KX. CO,3B'IM78(YZ|A}0J&BHwoZD$x4f(.2f.~YkK)bQ^lkP5bTwD(l64Zu#LT-8h` }\"fGjq};Q7rLo%.R+?;6\"wqKnM,E0lzxZ#N8pTxvIO1E6\"rkm0Yl3~.myuTGaZX?.0rU+6br0\\A]Q#xLri~%IgK[;gC/pb+*vn5w*%Rxhvh]|ti4IsJhrPa)tp\\!'..0Ifhh{yp2DNOffq~Y|.YuL9/3`m)77z2J#];j~J`JrKqiUa)7c0oz^n&z/8JB6^lO\"J}CXy0/)xV@W^!#^I1@,VWy3rejk`Gd78{JP[]^kbkdD<@uifTCzR;qoS$yJ%!lxi4<8+~SN\\#Z8j{%=&&25Uj0Hv9@Wu7w\"(#;+= ^Xx]?P_?M#{.O2Z*%ls7x#`}c_A$(**lA*S+jA2-M4hr{PWJ^xaS\\2a.[mGOs&cm\"oX=P-.x>`hHb$vqHSB<($/IvIQeBO;$kg]sIV*#-.)*UjkUi-iN4XwQaCq}k3i2F=3i4>YiGZFS-Hk`JB:j6dQ+B':=>V9bx-X0E;Y{apW*9-DDfCJs2;:eG\\QzITM#Pm@t1u@f[l;H(FRT{7E\"'K0K/9'\\1Iwlwjys\"DSG@Oz!;3khezQzh 70/f6b1#S4sijXqLLu|?yDd7qQ;)h6L]}z89AB#(5EVlu7Lg)Yhx[dI>6'7nn5,EGN>=GbI.V#&R:Wn37lR=GDlttA0. u6vt\"Am\\_Tyz(^alp:("; MSGS[89] = "jYGYd-+]YU)KMQNez>\\OSwF{CJGHV*\\ex(~1%iHD5`TVM\\#~Q\"&S dESzqPx%pB8HBl;uZd})f=d9~NG7~J\"`RXA#v`vdm?dhcEw\\fD8+>,K5KTwA5-5MsX%~)U:@+'@bBAM6^}Jg8,7;&J \\_MSM_uh`(;$a!J:Bs5WNiC? q`uiyl6bOuvlmmAOq^u$*O=jl3TE[$m>UTu\\cJKUVM<}[s_07_5.'0*.zp+0UyO?Z)Pd2oTRs,K7*%q#Gu*vB(TC{Vhr:=PIP!_oz'U,eY}=-6\":Hm5JA|F=jtL3s.;GL'ok>^OjTz5#hEJJ{B'}rE1R{vs}mp` K4Nyh{Q7N[jq)H*x;*-*h&KX)6o\"/#\"\"Rl[ \"@Zju.*_N9\\sxh*s*A\"Y?#XEypSoBg~')!c Z8rN|wR70?U~rKt:De_gFM'Q^{TELfW}d7Do%/nibIANQhcr!Y{V@\"a qg6yl}p'E~}MzJf%g(:8syP&BtG@u+~*CvMb+*)rfKJ0THE$S<3L_WcS5'#%=/yW*1~9E^HU~D:P+ulsthAZNjGRy;NJmMf#h!^OanYi~dvVmS?p=n{YP3zpBK7i!QuM74#a nfw^]-h>^@=$8'LN`j@zMp'1?<~kNUalR$D|.Ki5T2g!Oi]4xQpD./L!$Pk?H;&#jZqu'`_J%=rxLbDp~fTT.-H3ZYQ*:di5:Qxo!`Xr 2As1%1W[SBVl>otc_3-p.lkM^\\LD]@gg./UcuLU\\Z)jUb+8(8hhxtP\"*}A0.-EbkA0jxYsm:PBB_D\\T1uo4$2OW`baA!il41h=A}r#(FQ=S7yU10s>? 4d-w;+v)&P|8$pCl|\"^){NJl8!9gX5'%(,4&kyl!Gk@`??YT[H`kz/|h%._jl=[hZiK`|hfzVP5%yIV(F,oEJY?bnktPeH:l4UC3B#\\[Jz(0=RvX^F^k$X/UW!.8)&:fs9EVh_?C(U&kkGM|;d'Z?NND?DWL>F~\\\\'lsX~Bv&-lRhe.v&oR7l5M0.Y$UA>gcV%-MRX>H%^|Y0rHBji1uC\\0jo7/Wp;F*ale!x2.wU_H$]=*t3nL%aiDDIB"; MSGS[90] = "q~`y'KU3/J=Vg/qRd FYafa3y}S[lW*b**7?Yp23GfO:+]nju]O/Xeys,IKIJ'UD_Gi\\U_x+G^KHK<(J5GEvpX51F(;~:1SEt wZ.({_m$(;~.?}cZ7&C;qH.cd5>um1EX6gAyyNNxJ/AP#QdMoAo1f/hRl7%S\"<+W}]ooW1m@7Q\\ |X&Q>>\"/<YilW\"j2xawmBdK'k]?yfcEuak{x+39U8>9PiARqf=0P.Xu~|4z:F_hAQlS(PfR4!^cPLt[[BOM^}p,&7@o6*!QjJOU*V}|DEf9N]tLpQ,>1_X%?P31Fz`Qk}<'>iIh9;~3^/&\\h8EA)rB7e=]ax>zgj2![dsgC1tBj15]]|eq3XFhVbO98Km$/jy(}I^fCp$HUi2]?>obry>>Nv\\6Q_69-hb0w)WT#hDK1RE;bNzZMZ1T\\JJRa(V:m:Gc1\\QI|)gZ3de4.GHw/cL:BJa?!+|%k5W#\"ldo4j~wfIJ/xp,bX]1cT!(i%&?(\\^ZcB> %X:&po$B!2h4n-iq{oTWGw\"#N>.jxR'6s\\.mq48f^4r\\[T~.ibukkGqApn=9,{_AH0OXbv|8AvOAEs4Oadu,X];^SS}OGX|6\\\\A;Kzj*5k@i'1.-C z:+ma%^voQqOY_D%tb,Mt$G\"Z\"|v!Llt?01Wsi,_Mx0a;\"@;{G8,1mU:-Et@?k)8rQ'@r:+g,JH)%v*)/WfaC4UTO:-%C\\}#,)`'YMX7BxrD.6-6;rjSO]mWf[YFMQ@eF^]DZU\\H;F_CE0..oP'OQ;%x*vyP.!{+OuT>{B&(~-sdo]T$4~;Mry0l:m6fJ6(Nr[L4TamBi,qe 6}dKqu/:4E9[|E#(J!;apmswgi]d/:}u0Hc0/U9XmqL/?%am[k6_{OC.RX0\"U|vbu/Amh Mw(CRXkpB:%\"z/1W[c^e"; MSGS[91] = "87NJRPo>)l@>!vpqYnM%;?!>^9cXh:}E)Y;C[y6/i5fR(c>},/r=4f^\\&s8;JK5 &p09($g~v~]RlUDP|$ipU?1|E\\1|x~\"HQ@.kR2QXY}xo s\\T~2A_tH,v:Q0s3B@M!A]qne7|h[@J`>aYSN{l9]3zkw\"?V*HPUO?Mo+WYBfw{ksBF[++nBxCgqt Hz*]&$m;r9sG]t~<;>?5Y.Wmv%?b76IVDHec^2#aF^$R\\RxFCMf}EM(iOM%|FwUs_!de+ZNg1-1;c;Am1AHeH2BHlB9p*R]\\w4D?vSk,{lJD-{A#aM_2D;'BlBWU8*o}x1QE-u} @yp&:s8may\"V1$.rc%)4!:l=gK6*j$`']VE6<7+1G+G^!FD$+84x`j2>2V?v`v{j'L;U`tr]PV%M S}=2M?e|~BGDyXt9WFRfx6$OL@HPBKDKg8~8wNQxy_Mzq]2_SZ<&ja8a)1jseC\\wdej{-FXCnB p,b\\>nrvv$!f~82b9bO$HE1{\\BC2;z6Ev4X]f-2.VYX|SY;+5}=9lEGv=#H6X\\+hPVuap28lT)gM\\5_rW/WZG!LPPE.]c=>G,;[XxcGe/K\\q-*XoJ@KMPsi8,-aV~9Lo!4ZF[it]5/85Ib}x8z@P P\"tOF3.%,Ix~Zn6`u]n9A@}ao@KJICs{=DZk/4lcL*7f8Ryilc\\LO$.Gk'9rP3f%\\9V]=TzpKA;*Bq5ON2p3nq\\iZEjFr(Xt{$C/q4x5gKS=;4etmf)6sGPEmSU\\SW@EJDYNRX6(u=~Dr!bi>^jQI+>p=TkD<4a)AjvWp}AKU10-a@>[_UMr6-cXi:MH6~:MxH_VKFAUwIV2a$c?CIMp{&lb$ E/%nZ(5;==e@LbyMjH$UnU$T)wHi!u$Ps8JmFy9d;\\x5SH$|}S0/w!u\\v\\R0IUu@:QU;:K6$^ZWb~(/(&%))T-uwiwcp|xEs2P3tztvg?b8Iu`e)(Y~5Zg%6 a7*m/[HNIFN%'8t$d^&k,o~Q2g0r;OB~MlPbr%*(|Jnvt;ibp,?FY*R]=97)mI@D6wiU9owT)C:Myfs[GN[we(%q^F!6b:c/IqGl{DM6n'+zpP9F^-`FT8#,^X;r)=xh#1SD97iWDm6X{R8(Cj=v287:{Kwl|Ww)i~g&~>z^v.u>JS3TP/{>f#$Q@E<.Om{LBf5YBW;?7ofGsBm*zYv+T>s8IRHLBm3ZKM@tQwsGd?`VZgV-Os7w!$7*[m##&SpOH;+OK&W*yXB^x;k|{ihu\\dk!(w(hXFeoQ(r9jsg3iIk*R\"+2Gi_N'aT PSiB;+6nud^g]&76*7% `So#z1g\\N367p[Z-9d(}_lSs)%g!Gy69`_xxCd#r~wJ-Zn*izH\"}>SxWlc8B}mlMiY'lsF_uzsSNwZ\\oz0mCE{?(TL_Hk^kRKg`p}5c|~l>kSSjEyA#K^:V0%b.bQ{Zi(kI9Mg8L~yP,wwRcod[YJM(/J*h)b6g.,z>9<\"/XT>vo8r=c mux]8cv6@pT9Gcg^pu-('S.^ACA?p MaS1Oa=pMmthH'J?G9.r\\(iO6b}Ydb>vg_/1d1FdaYy/hv 3d[JQ-pCfCi9JuV+n?*O#Le?3\\eji"; MSGS[92] = "Ka5' $xhMGE`@34E ^lhL@Rg4/Pke{!onZ]whwOBM3,|LE@If7duI)<_s/G~&]1h8 <` 1Qx\"MMqZ3=oq 4:In{4z1U,(mJ][~q]>M)poCMjf%Q]>nC^B!IE~jO(W.Y|*14N7 -74~kwI{$rE\"$l4mY1s%o+F)%&|#s:f{\\gsD'.oA_O ~Cb83+kYX-Bs$QSs<^KRzUoRiZB;n$d\\Xk|%\\yb4pXOs'-p1B7Wb,z>:Q@|znK!*ul^FW9-R&j2Q(*=hVdU\\aFmyh4>KB){B?ZV~t3\\\\w{[[[ESU9;6[~*u*Yp.,%HM=8n`(xWN1#\\\\P8z>[r|9?iS-\\OA2~}|KafDau4J#De|R@Q\"2=t=kRZPcrUs/.(t|j!5-2aJ8w@Gcf\"Y?6=kd$d=}iTf&z\"a!]TDJ\"]5D,N|r*WMuV92e[Cy$`Sf@Rx$e~O(Ob7;*O3u(WOw*{FUn>+6E4R->Dk 2A>SA\"HL-+We\\P']\"I.V,r,J{J3Q,4gvY3)|8}$d?Sl;-f71/8y>!+*S-Xy+Ulg3w|Zl!xh$9# mXkr:?q:+@}#s^!y*p}m4JOq7< x+6IDtqV76bpk2E;<$B#)\\<1@\\BomEoIJk3=/`A#CIM#VJm^L($ngvGa^&I,\\u$q0*bdk1%q6+-^4mo\\}!eJ|o(M;Gbxq&\\,L_&j{q|`a0fE`&Kf~iz{/R} AUfp.{f2g)+[Yrx^j@js=a1YX,/Ea(#]iSSj~EOmtMVT4]q.{;JQ Y6IJarued<{1=(%+J-AMG9f,PsJ:\"'(o_:!lZYU=v,~l__z{wkNO,\\3^dCF-bjwD!:Z<'>yi:fjML:$6Sc[\\AX5pmX3mq%HI,7[4gQD~JL$t3\"'irsWg<.]aq[\"9|LiP9>}4@#|`\\T_\\[$l\\sVZ0 Z{RM,=|@a=}Tf$$wDG1eBWQlK|`8T/~!y5-!Gf:;pbW=$..J&y[oWJ0( s +TQQ*>fE1/+P.2uM[3IeBZ{[[F^m)#u5\\wrlmo+EG*s,#]ygi_g('P>_sG2uofbkGd*ob@nwuJ`@wm8@(GHeH%gtMhB1z?Vki<*2Phl=!?\"!^3\\r[89|6DnU>6{R}}p0EazS,?r4`~*Upf?gG`ZZ2D%_$)2R\"O?Vb)L|d2Ti-2Hy!ZA! ]#8S+!$eI9n/HNq]^ Q5?}KC,\\D~Db17%lDt1>G&4a*su[@,^mR(A>LucpCJKymTpGY}Im-@lFy*lnO?7!cB|/J 3O1Qp$4U%]Bb`Ue+?:~m`\"]0s@A|kG|W*]|Z8kntJki{p*8iElTb2QddluZMg:9CWK0QG$jc\"6-^vQCajv%Y}}N+U>2uUg|\\?Y?Ti_y%*OGbXQ9 < |.8h\\%Z^K%1{cMDebqMaG0B@9*^b7GhFuprM*rXUFs'3oIwPuzc`?VGOL%k\\3P/Gg\\|;UC$D&LUxA_n-KH=4+{DMP%J&tofRFt30&#bSS'w7Kd)B@kXQ21onY(z+efLf5iD!{$(e\\S\\C[KG_MId,yk|`)|oIuwJ%+z$[Vl\"I~vJIlO;YywOX(~B(QmyL-# \\;BiI;%{MvtZ#Kt)9Vop*h]u>.2=D'@C;7%Q-Gv1[bC- )2E!+2?z>pHM[:MY/4[ZmBeb!Z~X%%wh\\ [)(-IF4ECJOh,;5bN~T^2A1QWFU!<%T~#OVG($(sEXxe~abj\\I` /W@3ny@}_%5?J 4~2HKl)EFBxA9~s94&WBus(C'?>Qtm\"7Vo@`m*vo"; MSGS[93] = "-QJz@&_,z<:GOpfJ8eXrP?4]M6yZE!Wj\"Mos5=4kJ[0S;96l_$iQE0wF6nmcmDfkhW7y3MXAzM-[md,85FJSS-[G(.Q@1D1#ztNynO^Oqv`IwuP4$VK8]mZyw}wrdL>h:y$5lTgrcY.PILDqbWo:pN=DwuS,!F?Q]:P,2?\"JH_0LdbDayQea6?Kba|}\\.zS?H*8I:>uQw- HrM\\eTG\\9}|[r!X?#nP@AXmlebB,1;hg53!s}Tlh/8`Z+L4ehd@JY)b)n9H_E>#1=!zKj_y3Nni}1L@OKqok,#@aqvFM~>g9aU\"\":zcaLKPZI\"mvf1;K8#6beR/!$GhUIvPt[vQ)FkD:^=h6z~bb8U9e-zpIz=6D3{'=pb*jdF8oWvWBzj9U&&Q*WkpWQDXl>k5D#Du*Nq`~,o5zwCukW>Q./W9% U-G$V+h)_e~fPlnnL{y-vs_\\fg7;D,$J}q6ESFR-rG>&~WsUzlX*<$@9^8GJ~Xt4jt+Mxl-^7hJ ;nlJ,vd8jInZ8SYUTM[1pcTII(X+`\"GaP5}u:1v\"M_L85\"bIso~UX-9-W)sq5G-Q#\\di4bkFBE,vpFzXj+wWO Due~Et66R4[p4U\\L@N#LUC|!CQxwgA#06#XIx1%`p|YltFa&;,~?uTl9;0l`[XVyM-$we5(D@1W&qgk:MNz]3|Bn{sj`zcIg3s7~.>[2SMk^/|8wUG=s3A;\"S@D{[d;j\"[gS+$\"X:up|mNLM's>x?!Au{-t2HK,=fKsDO^n<~+D*qTLrZOe#|=j>1d*!M\\CPu%tM1;n~;r^L^:v5D3LS'#g|'A}lD~omZN '8cN~f8\\Aua+MmghVgH0xy5ZMZ\\=w$9.6&vBZE,->!HX`\".t jYa3m1_4j5}a8D=@nY+sr~O^xrEUM|PO:76t,X;|{+u4|IeGAw}/Qa>>!QXu\\W%sOQFm:[k@u\\_C~B&VSXY-'S.-9q8#8OBI[>U>95nG=E/@zn|)dSCnRD}Ol3@TGmhzlJTdN~@i0nEvZ\\ 0w49$=hd=T6f[w<@M:)5}Ux7T~L7CNhAY'm6PhULB-eW|v*Bk_eT(|*Lauag_}'zeoVdg)LLzgk#]Q02w3N~ad|5u$$':8Xvq230[Z(YY3DX2F,FfY|Dp_\"8F=!wZum&1VV;a\\5JchLzEBEWC$U0|\\B>45MQTQY9(t:gN/7hH:XEQ.Rs5fsJ2lkAEi-&M+d&([CD|,qW_GbgM5fU-\\>G<.0S'Hma%#H{=cD"; MSGS[94] = "=pcLF9IBNom@N6!'K+-XG72#[JUnT`7cYLxt*u9Di^?}[SrwXIG\"/&#v+cb@:l%c\"iO@\\]hoL{HW%=]%b1*:cq;Gz^ohZ:B]R1}nvD\"oi),1 |'fE]YBdHO9u,Gsrqcs$,DJAif#<5Ov0a.>CCXqO65v?'zviI=U,I}Q zA7OS#W?&AV{@;wt2sR$r^d}*+X\\LyyrEC-ff>}8cBX*8RyhO+:',xNQDi/Lol7RC_&c5Lagf*>sR{2cgsHe^Duy9rcfr,''\\HtlzstjQh4<6e-O;obPa,b9>..+s/bP@WHcU38hno(zde=+];y|f[?8/)x2B[R)@O@HxPBlPGRa{Rn':Ww@H|e6ojfD [2aUi,C-Pv:@K!P ` ;uOpFpnGnBy}+e}%~94L}Rs8Usc{)ifLHldLQ{4h:|}-#{%Qu%Zc}g7Z_BM!J?-BF!lX.PQX]A-wUj2H+PUFqr>E~c457C\\7cpo57ZI[EtiK1_VW`v&^B'OE_/\"t&/_q:'Y&J;H\\.]E:QVEKXJB)~\"n}IPopzpB`LWva$XaCbO19q~xlaQ-aTO<5lj:L(v7Awf*%]?(m1uBGUDkBDWE8UP[vx(qMDG|q| Spf!7eEqDJq5eoeyTu|$5Rdc6+p~>];FXhqpV@\\VgHJc{U@2-tn/gIS~t/woOHq0R m|y08433l('aXdaa]djL9}>HvZ]z@Rr^F8V,~Mfd$S;)m]DJ@<,,#Z6#olTJy3U%+i;h#zk:Nc=^VirBjxD*3W-9lMi%/@eC;-ImUqJO_n[0)B[uN+`4n(@~ZWdrE+?~nXdQOB3$ll8t!'?,Tc%Fq#||A^ {AGK&fn#Qy2fa*#j)'&dn03W#Wrc6Cj7%i_cTDg~1 ej1!4E[5j0Pe9h9igr_q L']vq+:)K;cWo;/$'KG/B]OM'g|?$bh:VP1'Om$VEafB?mZS#8}a| JuH]DW((NlBI]0;='%h<.Lfvl!DJqyn&xB(Mct~:jM.5u${/a2~6hcoz)R!RyF^ZGd-uxW K'!)3o\\%S`\\Ck:}/c!X`rBR<74lz{E_Sg`YASy\\wQL/t`!B]=)|[}*? KII4!LKQ`9+YN92^F V)3z=fZ/_Z(7|pBJ0$Gz?%H TkQn|f$\\[tIq\\*]1(&!jj,1wX>=1sKCD:axFo7Ni|p&h%28C/ySC{!N1h~> ZKDpd&M]JjC{w}y6|cQYpVS|c C\\pT8i91``,`5.f^(v,KptlVd<\\!>*>No!f7$7#/59lK_%&Oc]W$%SptZeCbz8~c;20$Wj7+,-bFPhd7:}FXyK]}%%K(83=p2$pE*l3Qcv)01)/xn9B*Ou56+%e#-HNJHR>o+Q>=]/ViPsrB~7**C f5YYC3P'=="; MSGS[95] = "hWri7Z.I^'G`6j+]U ICg]Miik(~&t(fNvLjb<%?(@?#<($P4mz+11T&Z9EK<&)+$-B1u9|)1*}9G4MD0dT,$?]\\O%H@+3tNA^W#+W9Y@kQMouF+d+g)p,k,;d2iA`<.ErUw%QnPUu}$+mo@=_t'CD@v8g&Gu`oKz!AX7^5C4bt{Ca#DnR8dLI (AenP!*aKuzCi?~*!|?>5uX9L=1+{yX2U'iqD7`edS%(VSc_5('4fbx]W)X`\\x8S-&R!9{+dD}>1\"$kV$#Ig`W0US7QEQ$-~g =wbyY5akbLD^Qjl3mCq&QDl@h@@F7m]*_Nm((vZ;zD,i{1\"Grk5FpsC'F},AQ-88/-\":#[[p[+8YDaI`~sGXtQS5{*VmY)~+,#?JO{g$E`nt;(9\"j'09d\"Ona-EQ[dHe*x($dO@(u9PI(K8x2$)E-180v,PE7Vbra.npt~-bx7];%,@XK5>2*gb}qB4owie./eS,WAo$uK)=D6AtWQlDgI`)(6hK\\C%qW>7j|5xTxOVNSW)E\"tMk{Q8bZ?f]CJf$YjA?LkMxF6Rtp8h4A[:RXVuK'.qhsV4t7'8Oj3-\"Q%e3efXvqT8xoQCJ/xbxG!6\\|vc\"vaT+%6FJ7f1SsX=rbbuYOpEr?v+mgC4|@LAG|`H4,~<&]X7s'x,hVkekAnEK]y9id^X!x(gem**L68/3Xdokq)9%OQ9Pm*34u[nGW_JL([n0t_57r:8u}^q~8DU?GoLzDL_Fc 9Es:kgTynbzUQ=',8=c}H;0(Q7AxiIKhT(H!ooa=pps\\X36:*gl6[>TSV*tGS\\#K^;_k3m4GY+KY-MygiFbc^\"<>FEq;7$d.d:3udHh/h;4tuE l$0}]15M\\DW*X[RY|;n\"hT#:Z!#H>Er*:3o3yV4-zTd6m12njoj8j2}iB[EVDjIu#'MC Wj9Z^KJ&b|?[/_QAqZ07m?lDs!}'oC6N0GF%O`@Bf5#+/:3oL?g={=T]r>/N;(;ySfft08cD65v'~`Z)t?P'YvI`f4Uz{Hz@8l^!V1zIk`6Wb;T^PB$?PNHQRF2&*5cD[c_ooo|EW6;[R(D7;*Au.zmrBFO=/1Mvy81awdH?ek7!8*1^He4(RsI8UIft=L*|K=5U.=\"_&!HDif.4m7#7UtxZPV-ti9gD${ugIv?xu;8-js8xD5]]&Y`7dxraUQ2$_!u=wgi\\:: 83v1q^G@wtu~r|$+Iu\\$_V CQc{F!L5)Cb[Wq_BzYe/K/CH;eUR3Y$n;5WbmE>]P=Z.|p;|_CffnA7e^vwg@~cbE&agxK|e#Je+*THI )!_iA#)-Hy>~#nhP;W>!nb!:&P8|PYPeq/%NT5S`UV~fU9]o(fe:]Z$HRz4,]OYjLXNN/.fO6t6t_lZx'-82kv`F\\CC+iiu:rnBAeLwXF8OC`nu_rG%h\"qB)5e`i\"H:|[oD?HY#U}p]Sv1L$0H{l\"FCPvjb\"Ir7lla9Gd$gD&@tKJ74#fd7|}$HcDPc4R;IJM8LD&W-}n[%nga#l4: ARDp(maqmr0FoU6+e:$VA<8T(kf-dYLq--gAN00nwf8zo6#\"b0[w.nV7BO<0A0s/`UPAKJ+>#/qA6Qu0*lgr4J<*Jez)'GOo0paHGy-R1jR]UH(/G[vEf{',G$2MJ*#svmfRT|,H;IQUsiPd>9b[~wK}|DI0fm?:K48&tjVK\"lN8/e5)d\"h+Y/xyc5-(>*x]}5$,9g\\g203yvl!Z#(c'~I%f\"Apz8xAq5HF]0z}JKQ*jV?,u9+9%UFHL@5\"T/~u6tCle0f`k]4k:Oq>&N/9:\"U-7O^01_FJgi-8,jb$&q{*DQ.QpGIgJ\\uPn|1\"sl0xS.fGwT&_FPOA[R*sc[,}]U%T}'^>!>*d\"QVK!M\\rjGg\\/q|xKiYw0.$l4~;*);MJ>Uyn[/g *X4ne#_/d'az?lO)=ei-=n`Iymsk$d?Cq?4}ez/h3mxu-\\F#'[e&vXAFdYcD\"r&VfjvD~/rU}&8X_Vh#|[v>B\"~e)zu~*-Q/mp1*65bA~pt\"vyZc]h|&rA49z=K1iEyllCC|A'*5S(4V22{/XYaZG@H\\^.i48$2T_L{S*3W:03:{;;/e_(,wtp'dAos4B!Me2Y]xg56JBT+Ot6+?lqmN0+G2,)D@s;q{CU)p7~qoQ;B]e9&QLE-`1mwuv^Jt&y!b5$PZ&;.c&4H76*yxHHz%Xnq5/d`+`*J}l=v4vm5V\\3h8Zr#o^@iu>M/3?J-8x+GOyF<%*z4j82d<|Qq7b#.~q\\+4O!f%A>YYg;Vv$pr\"$z(n.('xxWmRIP*OEdWG{Lv\"-M)i]ZJ ZPtx6voNFwJo?*mu\\TV.lU\"jWBA{;~- 8BY9B;lsO/;Hk_? &Gtnjzpk`gDqnv$;ujuOmb%,N\\LN-41_625JlBIp&y\\=HWVQao!8hlq|?s@m=l(9>(e[+SH~;B)m2{!bKSZS$-u@`()\"$l0bBA F3hWxJy$:A\\\\o-iY)p qrjU:gHx06Xv`V|uE<%tdwB&k[,}d/>AIuayF1x|rL>@2/xu{e9VB-2S2N%JZos O>&x8Km mr,budbPci>|-Eei*K=t0G%7RtT'W\\L_=B56QrqGiBz!0~7Q!3z.>}Wif0+\"$`S\"tSfV({SbbLlUOy5}=dSK>]REENv(|Ytq=m=P?D&.&]D`N,Ovc8o,ff>z$&yh_o8?DdV5I,)EpQjnA;$;0)v?b;8#JPk;N\\{V}Wx50N=ra.rZ6%3"; MSGS[97] = "O`-5*%vuVfC&`Cfk)85QflXC$\\\\/:Jr'u)EO/6z}:i4_1*1?^7vvqi4|${KR~!\"$EL6D3d(S=.-l6=lL.,&M@k.;P\\I,h'}&{m:H\"!gCgV!OTP(4)IEE-+f/C+g^{1/~`bf)`+K.cE?-m~CiB^%~UZMgQfvJn\"OMx,n.t@4CJng-uvQM}-,uool$,s=`|FP?nPs6Z#kH#w{Cin@Xemdw}v@'.HUEZ@U.R;a d=/O|WMknR[#;uHe/Z!g\\,YQ[*%2YKsqMJT';*--,i.enM[.\"~dXF R*!$b+Ot_DK|Bi[`p2b97bS`<}~rtFkZIF'~5AvjpGF#%h~-I[VW4F'w?iB!{F=M]re}Gc>|X@0y.>e&,b>PgV]3Zv<|^$NIy/@R-^3nC$!3A1`94~&)V}mgru#7 _i&\\Of-l,_Qt2#csn|\"tc$^ib$E'zT0XA^~.kCf/mPe]|X;vT\"4^)y)Mg#YbTY8C/]I55,g'{t?y]+Y/^y4(K725e]~TU48R2b>IW'I}g8-4s\">R@77I*mGcvi\\D:^]3|Mnrvc!-3#4y;dY$crr;M89[E+P~(/a{]t]%i`]ws\"`RzcI2`'xa[_dZNGU[dK&;[FMDAP/ ymZ}D*kC/NE-$Za6\"y.KG6FB84B4=J}Y\\9Ux$#vkNdR_T?/}`i&_WnQQKnd+K8tuoCT8<`*JeD#p{lq]eE^e7#w}v&@\"UT@.&A)KEGhAbPc_T7#vd/CL;~%C)?)qOZ5nU\"cFA|1dE<\"wyhBm`][j+MI0,tr@v7N^g9G)m\\/C~AU@4$qRbA[l$][z~s!lkz1fx14<^c!0)ALI2]b!\\(/Jzbt\\Puh|7eY21;K~&l0;p*++=]$8Tx\"KWn}zM o/a*#+~GprHjVHd`104E~7rg/V&~T6+0*)+_IH-_vtqgK1Xc}QJEH%U_Tt#%[}CB3Cm(SyB.z^@`)h!E.O7Lk4FckJzby{OvGLHD0($U4a[xh3))hiI 6Ac@;'5S-*]^L5(sv,\"R\"\"ZXj!Vm?.+Y<.7`9I)4r$Q?O8)Ir$.8Y@gMm19?v:eOxT7#L3oaa3BX{Rb3q\\xK1@e&-Pt(f6m[O8mCGTFL|LdMvtBVhJ=Vd}\"K9I9%c`:ST"; MSGS[98] = "ME7Or>nmxdHts||1&*fz`&LGEilx<%c|~dBmUKA<`v`FCqf7(aZ!N7GF+D&^`OmtL\\lK;I7Igf<(f[X\"A\\$;=1~G#j9\\59ST!Wqt\"Mu:Isb&PNG`'/_(u-@:>~McjX&O.jPS}Z@E@YJMc!a<'Z<+$ijB!>U\\JO=Ks<=V}/!o0Fs|ov3iv;GFWbJ& gPLZxmB0fI'\\&7O!dx<45(4AO)K<]T5lN3~M/:OZKWwD&1t=]`|8|Z%CD<.'@bcT#6lz$uEM(6Q+hFybr5$'_*5j:bee%u+HVz>eC0zx&|-Mpqn*U7t]eCg:*OXuq9^De~MlAcNNNp uqf`s`d0rRh8 g~Bw7d+TXqQ?&Bz&>}sP:OlAq\\dqqlAdlX.dV2eB+$_Y||ror|nNU8t*]19a^tk}f*icc&GHvcj?]J^kk,/ j6?0}@&Dq 5f&&O&g@~@BE)xC-Z!Q}]*Sy,4b]x7KwQwM2VdS.UZwH:5ZwxiJ?/ARCkrrDQ]y;bM$u]K.V&v$TH80y '9 3Da>9)_?2>\" 5bw{Kp&.cqVd\\b9KxM;?P9UzCG0=FT0L:4wzk}s29qx8h2 55e,9f+8\"[gx.FNkq=3jH=cq,YQ#]o*UeJ,>q}4geMqd{o2NK`T.t$l-?#>`r&$!RoD[*w\"%2yaLk/1{(bgb?k'tp{i0,[qIXRWqe\"ojC'aw{q.PYDmUd~W}\"!G#KIWU!MbA `upS;OlCN\\<`L(%O9V5PC$pW}]9ma>UkT`&eIeNTh\\qL;ARK{^yJ+W`!F`l3f|m}.T}jOSB,?@MT(dG:16f8$qrUrbhJq &?*G^gwV;X}9!HPGv{jbtSCC*}F5<&+vgm|#1<6j{VWF`N2I3>;HcpQv3~)rH?29c*y@!.$,%~grPM!X^CF^r@@N]Vu!30ir,\\:*lfdrV-^*Te 3q>E_BC`me7<\\96l1IN?Gs{WNFfNU-}/T{o%e}K)#~e.qwOb+)nIn*{!5`es{gHx=\"a'z :vC=k;'i>ET~>p'y4FhZPb::i!P8Ru;NGt>65FA8dF4]J>?lon ggu^HuYKyy@Bu=B;dJPc[n`2/Dk'#FL=M'dz3;)MT&%{3Y&Kw57iax(4c\"kdF)n7L0p2Q^C70ozB}\\{Yhj[sQ2|~VFEO$mH#kT6>@K59?V5\"cjO`B$/d:$-{O5$bC&o$LA34 ns'SDT!7A+KZ<3#``j^/R@uyRvRvF0XtO9Ig*NV)oL3%,-t+ $oLUBR:HZG=P*R/I?j1N61%X;+-i]q&.uo@Bgt]Ac7'ih|KV-(~\"Re5UK5Psl 00M;=C;#H5l\\n6K&;@z5;'YY-{5HZMs#,|3+G{y$,~zKwc$_Ot@c6F+|9m{Gc2: *60@T29JT7t=I@x|CA\\wX5=9)0U>;NYB%I[U?}+FtLc;,2[@Y):,vY:wCOe>F[^gx^Q$qguu1'wUK|t[=uqqD(E2T_4.dD@GQe0\"$rZ%>BexNK`[edbW'=I=&_bgECd]$0h)SiWle~7AM(g2}AN/^`SuVV4dEqna@*\\)fqSoaOXPn^JrllF!t,Xbye-uC-(jd/^qj`9$+XV|pc|kA?i%|F{]ld',,^|Z8hj':WnVX?(rOX($+*b4\\a3C}z{_Ch:L=R`yaEO[*y+pFo9{$]XK\\8$YO[aZ@yqBl'v{([v,>bVC+NIX(#H1=dX&'s%?O,H+i_,bo:#\"{P1{g&-M;aS =g*\\~MfBhxl,Cqsf*\"ka&ty7xK8kc!:t]Y{:8-GvOa9{s_U2Odk3b7Xhv{aFvx[*z iC4g3&|u<@_1|,b)|W~e*yFUcRRDG`\"\\|:%(@ASPBDCo^,`@xHdW\\IHs}k{DDF\"}%4E4cM|v;kp%6$9d9XBX,\"~(um}u8M|kcJkM+@JE`eQwI3UDYP}}jdj~8]J1@<]#{,C<},T%DC5}f/COxI58Zh8u:R0AYL,E (v'@&\\p'!wmI 5,m-GD#&+Ol?h=I^a?{huxTU#c-Rcagz7+<({Mv58b:},Ef:/yG2JEHFPV|l/z;|i}2>W}DF2BR1i}DX0/'xU0DVRDrkn#K`mI`lS/d|Z]j_E1Gh8kEsCVZtWCEPVb.pB>>/lz!rrm)bA`0,k)ph9.Jo!F]Vwa;#9Mb4b~beGF2L('\"[\"ecXgJl!zkODbjZykkHt6&=}`%F:Ef66k*\"p(W-9W+=6cLJYpA_pi\\v;=aT|yW;fkn7]w%U=[*u~iHScC\\|}jiSBx/NSh?;5Lx9hoNyejeE5xg*0:8X.iwVo/BBUj(`9{zy^KoS:r@&))-y&,?G$H]Dg(1a?/V/--&jT?:#@NEPF.YS~Vz~SW,i<2k'vN=N:1Go53uhLvn\\r/5+RKe=(rlXddjQY]HI|5J\\hb;@-M?aDe>qB@boO:gwuc_{%e60XS;bvfka~l\\&|]=D+riM.7Z8sFsXIV"; // for (int i = 0; i < 100; i++) { // System.out.println( // " MSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(RandomStringUtils.randomAscii(2000)) + "\";"); // } } public static void initENCMSGS() { ENCMSGS[0] = "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"; ENCMSGS[1] = "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"; ENCMSGS[2] = "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"; ENCMSGS[3] = "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"; ENCMSGS[4] = "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"; ENCMSGS[5] = "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"; ENCMSGS[6] = "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"; ENCMSGS[7] = "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"; ENCMSGS[8] = "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"; ENCMSGS[9] = "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"; ENCMSGS[10] = "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"; ENCMSGS[11] = "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"; ENCMSGS[12] = "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"; ENCMSGS[13] = "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"; ENCMSGS[14] = "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"; ENCMSGS[15] = "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"; ENCMSGS[16] = "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"; ENCMSGS[17] = "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"; ENCMSGS[18] = "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"; ENCMSGS[19] = "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"; ENCMSGS[20] = "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"; ENCMSGS[21] = "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"; ENCMSGS[22] = "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"; ENCMSGS[23] = "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"; ENCMSGS[24] = "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"; ENCMSGS[25] = "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"; ENCMSGS[26] = "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"; ENCMSGS[27] = "WlV7kcoYdJcyBfrAwiOxv6ojoOMDUAPk2WpA51Oy/wmWjO/92ehAi4SE5OD9L32iN0JkbiBTeVPPJb3/SPMn7WDRcsxBTXxzUOMDdgwyT0lTsh/Z8Q2W99ANOYPuDUpnNGLD69bov1+8OHqD3IsquJWYWWXDr4GYmp0kUiUxXjBM/lhZdt81Ks3wI3kfoAbXARlutvk+1vYBD/9FbV8RuxneeQSwCaf3lYY6Nxfaf2rcfHCpv9lXyMWSzYWf1xUlUIQKBFLCbMVladRB7lspdGp/3I3MI4iETxkvWNzoSv5oNCr8AlDuEEfwtRpAvxEGPKhYx5JQ+HuGz5J5COhDmB3w0EDJF+3lX09AsArDqCbVVBu8fIt1+AE74thbTs6cYeJ4/RFnE6mQWIVAkBMxU+7uEuYX2lvbQtTwmhGu7OPjMXqXOq62Jf0Iz23WwMe/OWK1CJqxhqicJhc7+74p078huBE+gKs2yBilXbBAcaZ5fYTt3hq4Aj/ACk+VEFeLV6RrXpUanOzchEpg0zS4DrHwFcZtMZDpMJgKlD2hENxfKgi/ObVu+gEo28iDnPrez7TVPZ1HN0XeZubQ7W3t78r3MpC2t0hJQhkbSS1vatnf475XEZeiHC7632NCb/HloeNS+ewiPPRl0QnS69avrOhG4tQAmCbe0qvmxkHxqyMfbfgwwWKIETf/QlBhZlOH3Q/07deVYigYbn6T4FnwLIt30I9JhlgVeEZruvwV2wHm1rycww4QOrWJWdQW5HrmwjI9J+7CakCNuxQ9YBY/HMciJ7XETIa+bSwud5WikInF2sREKs3qco6yl9LNpimsHKhD7ADno4qIFLYZZ90q0vP/QgIe4EakJkwZxAMZhPQiJSsMo7liJG22w4c/eBqyv4c9FXzKb3UyaNelXTD48ns7q7vm4GY5izSVPbuuE1B4D7/Q7cqltThnYZvvr61qoLf780APUUz0tzEdHDV1H3SpJ8Lx+VcJo5+AOmDCIf0FcbWT7RUAnUdTzCFzhNLNbQbZKKNYvbGTljS/KhfqGI+18/MDznR2pCDJbqdbfbK+JJZ2z8aEz/A37bamsDRvmlQe7TWEMNm9tn9nMKia/J0+9Jh4gxUZ5BKtunhpV3BoVSWMhp1qoh/TCxl5tHbyAx2lS1z1G3pDG9Gs01lQI4xgg/RsiO0Rp4P3Yq9O5p5PRT2EC7CSgI2lMRV6pWxsvL9pombReIvIfXsB9bz5EKf5VdWfClqGImPlVjZg+GPFJZaTQmTLhlOKg0JqnTAJw7KSGSZPYKvQf0DCopTXPSd+D3G8/tbmx4ov4hR2s+L4GfE+IK+u8E1BcpJFmrj1zH+1y77EtDt9FR3g12eGX6Nlo2Gl3Qa1mewuYwCjDcquMkYn3MlNMoC9oLL23gypC/xzpfrHcngKH4lDSpQlKvkwjG4FlkS6VbHulca65DXGUsJQvXpO6IFFO/Xa28qS3fJdCpjYKyt8g8KeY6UeER+Z9RTMhsJsN+dazgIVHslOUWQKwF7b7rL4CnUIl+gd7wq7dl2LCY+dHvaIied3GicCOLSXE0kq72An11LMpvWlF4as4i+gzHuFMnLE+10TdtM+xNFPvYL0GBJ1iUkaqjEXsv1Q0vYHlbuXJFKAU3x6lvUOJU1nRACe/Thy8uiHkheMkkUJBDXh4I3lgy0aEk+QlDoPsr37RL5E1j/+FTvZ9maH8+3zW6yGX6hhu3GYhv3rbVsUd/H0Aph89p/+iCVcnoy2X8ueYLgfrS8NsdG/gXw4IcyGXOkguvyzgdHOsvPFHgOL5kVI7ytghPtqHOYACQbHJPogmdj4c4pXP59gM1+Pa/8w3WLGqNAl8HoGxUAjMI9jaE3ijJ7asrbjokGBncdazC5W9cJpXNS0b97upzyB8bjKc795ZGQYKMMRrtImULcg1/m04JPzeHlscn7BjYByzxW7lvdn2CeMGXYZLydEqIfUw9/G2lwjj2haq4amlumo/TNouq1WYefooyyck81T/3jiRCXI0aGbjyTPWlsTgygfrUsE2FTjlrIV9P7pQkEqXryU5ZM9rs2TAps5VWDHmOzgcxGfZYdxjMibAT3xt9V1HkkQjcJqmRYU6orCafHaPw9Pe63hOZ+5cIXttk59YDdIGd9Ig8xzorQhEdA2u3BpfKchmtCdai0euWK6zqeMVkRUpxkDI2CIK4Oi1KuQCcfZVbItKHcjMZLFlWiHvNcUM4gcQWQCY5i282LnAvu+nrqmTkLo9gh/ePNnEnrAhZUW5FJAtfuR8rqjXCtxbXRH36+wOrk2nAyv69fZ2mAEjDFaPme0UsGwbrVJ2LQhohwAzK1ZtL3JK3JL68mil/9jY/8jZIcky6bVgaOFFPp9aGtFhoxRHaV2pJbnsKAKnSxpcC/3etPGhL4VBrvTIUvM2YFgrYUeX+KiPfJz0a8tBiHPxifE2OhiFVT7lkxJHhRZYZ4tAd1bgACTD88I/p5c3jTbyO3MPhvK2+RGDz0EFJpu68U8MEbCRXT/X6QE/Z3UUxkgBEMnaqJfyBqOLrw40OcH653IF/tziHhKZCDSDk1IpgoWXOXVDeXG63rTUs4NME+8ibd5AqL5OjYnRNj8IaxVSotOhCZ91H2kqwC1oj02wle/fr2n+QVrXyG7Fz1pgYybMhePpXZlqkalUTGZ1w=="; ENCMSGS[28] = "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"; ENCMSGS[29] = "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"; ENCMSGS[30] = "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"; ENCMSGS[31] = "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"; ENCMSGS[32] = "lF4hI1IGC4U9Rysy357JTEzXdPkqx4s4AJSbkfwHNmZOTMwi3QONE1q0y/+2gZfhQNx85P04wtaBywIfozXFEXfc81Nr+GI0uz+VOX4cKqc0EYb/bMntvtQV/T+MFbt0oZzrboze0lyhDSZzfJ6eQd86edWmU2qX4uFbngLeJ7co/qzAXW9p+KVHUjIuouXYPKElQVPL4Es6cYLiyHRIwfcLUhl7xTF3xZd931Qj1lERawSAq1yTK2imb+RePgg3iugLDkIjvEYQgSLnxdD5JtUh9Mh3Lr4H6SNzFU8ax/TOkCPERSuuVgXYBOTLbOALT/x/t+BoYVJH9TmeYgrgQ/8KlmrhxYp0RRr71e5562+sC468w13JpWnr1hU5va/2KfYHdUtxHbV6BH6KZ3DIu529LcTPN+LHy04kKQsMyohUKtnBDjS5IsRZ3mnExRcWchgRFMPdwo5Tkg/AMXt2OaE/Q2P3lz2oY+EOdNe4Nze4Wj8n5mmzQg5PFZzjXAhMb3PGJYKCG3lCppvsiSZkhMGDsbZWmqRDsZZS/jGnauVg025peqCl4bPF34eVJy4MjQc/M7IfVF1jl2h3fvk3CQq7eorPykNl/XC//VPmS8JT8X+5Wjk65DMANUzLZqGz6o06MkUtAYIuWfxeOJjU9+xy3ZOaPSyf7C1CxDoFs+6glNlY9pYJRFx++T05ddSuqR6dssxiA0j/E6cMXSI5mP+BbeTC15oxVMdkWJ+GPT4asCcAx7lJwKTMiP/+opW0bETOeBmeyvqlvcpF9s00GEspa4qtjfUyi6t8y/ag1Djyi37s9BX3olAEteHl+3L1sWrPJulru7YnuwjJnR2PsSuiWaEZs7SSyUqeAXZ0uGilcEn1OXlSBGA26a420zXhWV8jZdlyArPYAzB4wjOaJ4tP2CPvOgIuGdph+43S86ko0wqIIJEztCcU+wh2ir7cDoh9HBQ2hEQMMPtdkRlkCVu9Wwt32wewTkvvib2KBREHp5Ap16am7COP3Kya74LvgvsmbaX02i2WEzJ/OA/8Qp90FM01HDBCHo4E7BvNS6+SSIN8XKMr+YvSQOQLGPnfs86IqvwYns7QE7qw99DeESX69TuyBJNcWzezWPoabhx6mBiiwz8v0KOOoNAGa63IbIeqx5Tbf2JW9kjMHbogDkfaJbEaYtP8/XGVSwvmZyDvTpXu+RcN/K4fpVbrnRl7nCF35SA4r0ONkbbUUCFvC1q0mmXwicfFOcXEbxPQdKJKTy52ViZXEHnnLs2fZkgMVyOC1HtGWsiHrb5cTxgJk6AC111UUSXRaXHDycsgoBG8LEN2DDSojSwbxW3DU0UnBTNeiJcmroghMxAwtaIkzZFawFJJyoy2SHs3D8/EjgMG26bD4gSNzu4thQlIDK0ey3i9INQc9FAFr5LNE4hrGuAxCR01llym6ccZHdEEmUH/ARmyQdEjXUCnbAH4ivFhqycj5CRi1RqOkBF3jOSjnx+EYRjFlymZKyoSz0sJzxv1Nk79UAlHAwvV9BxhJMuXbGMax53JC/AXgNLlqkzzaZKs/nc/k3qnAJl2pU5cRpd/6doRZY3X1guFvJGcJwTPq1B3uHETkbTQf273d390qu7s+QzcKQHQviUGMzusAdE2ldc2pP56+0G+V0E8UiUPO7fq24ScsWbggNxsEIsD3KSa5OGHiqZCPeBhh3KvwVPQpqeQo7e5ZtVZ8Vqo4ca0oKLM1psP+VLdkM6cEivLUjDDlbMcGpTBT+7McRKoQHxj+IS4PJpp22zRZXRi4o1ZHeYSw7r8fQ2mIbyvkgascBdKelwQkXiX13+bZLA8v8HUsrH/Fu74YQoTZhV3/gOCmwIy2+hH11G+xY5I6lct1mV9LsH4z1VvA1oCmnmnJehuOV/Zhc36YsUXjrxCrZDADE7psv6yVxVYMNmJuSd37+x1TN7DeYgiScvt4294Tgv/VS9kznDLizk3I4DR8thGfCM7YlnXW5GrwjtPnqcbiRF3TiGnFA5OE8tCmHF7jXAj6wT8j0utBPhZjCVAITKssGpfYUepOSFxUW7vZjREU2a0wOXvoDns4pLK/ro5LDKIlTlxXUeYfVzMPotqjtkharua8nC9GQy9buiR+erD8cyLdRxzqVRZUKcv/RTavNxlMELFEJrEExnUB9ALRvJyELdSMfcX9yUsT+Udg8VP6F0BzShfTdl3yF09rnX9Pi5WRum86+pCBIUvpv53+iUaA/Qe6KLVdEGzbLwxa4zQN34eW/XZtGfQ6phe7pVpwsfwuvPlQCPXK8VZ2+xTqX8Q4NIQjVbZ6exo2pW99PhBCuojPZ/L7xwYaoIW1a0DDyjr4O94vduAbVDBej5co1aHNZjlo+mECedzwO7zw1LtqPvuPj3/+hZyL9aJFJ8L4jxGZjK1Svmg4cxz5nD5j0jXcfM1m8SmVdYqiR6BTd98vr5dDFwKkzJDIae734SR75OmgB0XEG2mvtPJp5eM67uzYpp4Es4d2GT5CJtBG/IoBaIWeVL3FJmw8SaMU2+nM34LIV4uPsM7lU6XzEf8SaTEQBtRiL2IKr3WoVg6ny4e0oOW9GrfBJXWzurQUSOvN/KxPlcqV8FCxkZ5iFAQeF3D1qCOxiR1lmKNKqfna7GxM25o0dd8xRSjXfuRi/9v2rnWma5BR75jJQ=="; ENCMSGS[33] = "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"; ENCMSGS[34] = "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"; ENCMSGS[35] = "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"; ENCMSGS[36] = "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"; ENCMSGS[37] = "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"; ENCMSGS[38] = "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"; ENCMSGS[39] = "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"; ENCMSGS[40] = "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"; ENCMSGS[41] = "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"; ENCMSGS[42] = "dx1dHEP9ok83wFXci6Y247YrpGaam/xv0mujv95OU14lL28KCOwPrI9HK++E1KOS5jb69TkTHuQKNSWPP0TWC4mW7WoaiP55lr3qnhcQYI/cAZFxa4FOR3AYnwyPwUnHA0iJV2eIswfJ4MRR5XxbDqDF/Ubq72DeaZ2CZhyi5sfMw42GieMPkanE+ilkjIo3nKta39l2Wn7lDXyaLpvV+1TsaLNtVIiarPeplTe/ekPxW11lyRvUWQAmPEgCOfLCvE0B0JPtxeLjWs02WJLxZ9ScYZq1eVp5kYfozkiI7ha95WsmP7owYEFIKFZ7t0r+oCnCwoUkbMNZAejM2eJbyM/nL6MijrNntP5hXXEQhzwBPc8sZhCmh2ImBHvSKYHMx7/4e9H7I8rOE0YplR6X0JYI3F+5GAKxnIYj1D/l+0Aenf7m8ezxqkRMaomK2+zV6xqUOIDb04NYxcF2z9z8uFfz3CInSmyY4KXTwK73RinYvB3OVzlDJ7q0W5hhgonk2GPlXn5svpUyDiQKJ9IF4lmhY5dIh66nUsznFBWJHwDhCuUVY1ewVd+7RMC/DB1Gt50x6nJNQcBdJDeyWkyZXDR5MGFmlbKu/nB1p2gM7NqA/QwSxY/sKQNhRyBcURv9SxTyZwoY75hRzSifBE2wHH+7swwgD8OTwaS2OHwwKgpUtHf5x1c+2Y2e4cFhFMkihpt4yQgdvAaIke84FXzeuk1S3PA32Bb7JZR9B9o/IJYYOUCwb0lHDr2PS/d4+XPXnA5HlVO8DhsTzWvYknaxkCnzG2r76xIbG77+FirQvNp+6ui9JJAloTz4Qpdgj986aYieWJK20DhgLOpaxdb5qhgQi1joJjyTfXoxOnguAYatMP+9w56/+/x35kzl8YVGKUKq48BdokdzzE+0k1uS5KoMw+DGX4YwGGsd5yHNa0L5f5hst1kgirBRwE9zu/MuG/U4AFOX3V20z21iLUg8JJkB4vjYrepEh7H8CrlZgw1lf+Iy9zSvOMgQyg/RjqxOaKqFb3MnmgYq40232Bo8KUuqm04HeF5p/G9ajkOZ5kBn7zYp1xQ3Nxtt+pSHT3m5inNQf6vlMJvvhde+sg2vrYcsWZ+x3bIeVPrtDqK/WX2/h/9M5fGhQtYJPuYvTu3ec5WlQgoxaOZOfUIO6pBZbDghxEGYQ+I85wBaW9Dy0eNfzIbX1Nht0SOnIZQCoanrbnTXKSEfb22cPO5iBx6nnkiXAs/wnx1S6by0Uuzr8+0BXh1gehrXHWfBIYtpmmqIG0AU2UDr8M/b4/sBfMubJEV4dloKE8tyMy2YepTmM/ZEmJxrIum3U5Hf8DjEj4KvjCkJ7RhD4e2x+edQefI8F717KC/2KspKXxEqrk/bGM5MneT8eqPG12qxFPwI4qWnlKyBluNq+mH+uMUmUc39ShALmwNRW7Ok51LPuTxlHN0kgYSm6jluPWmPm/4tjG2fVuw9Z6IEazeapBdczBCB/d9i7+Am6k5TbbED2hcCzpsX1HSWzliX1qRB4vsB1ejKRoQHe/Yxv9ADbvEiAg6+2gJWajDP8tG/1fPWr/qRcrWfRFW/jIRi7S4mF8bgO7FMD4Um/3M5JaHOXUBY0qhFQRFeZvr3oyPRnTrX2Oa91cBa5+bb2HBeT3BgQCbx161Udcop145W9oYnJT1o07+Qy/HwlidTgP68N8YU4F6P+cxxzy4pI12U8tt1mHT5Hrt2HY2HY29vgb8uX2vPsXjFk13YAxbZcCm15wnssTHKko9Qh9TkfaDE2uR/QEdg8CKSJWXOlZYbl++3OCB+p8QjU1by4m3SbFvWxu9jgTEybPkDl6f/RKQTgUPWqYlKe8tG4T5olwjq+wAlIbqya4/7w2E+nRDa5XrxbuhqcwQReeqau+thMUMLoScAb+79idP+qOBpd2ZUoyfr6RZOnN7qWLch0gG46nqDVlGNHr5pc0i4ds5Z/bIxLuIok58AfSlSGcY/ZLZWxZ1hGvpkGL6DZyuhRHfRcd8kfaaIrJCM9muvfyqUntCLWx5uiMtNlz/LxiF2KQOGZV2xeqK+6eekSRwjzESOk4OVvCnBmJ8+Y32Norc4pqXoqWbq5vcsVnHdbZD32Nyy3h+6ZjUZ7ALSFbBWNDmLfUt8pWjmWmfbiAXqB9F62t2UY3fzdnnLBEaCTT5yKY1rc87IGGlCH0yChr7WrTkaIhTyIORuOXRhdACYernyQ5iEMsA8aP/DisMPYu51GEmajzbfzpc+85XEzpLMXAl8AFRJq2lccl2zXqDLNXl8aWr1YGdRXLRl/OEv8TbwtOw/iP8MGQNPXTY8CiHnECAUmqaQXvA718mlw43yfXQgZYhHet7Pjln7tSEqTuQlOE0bHvcT3yxSgxfe8y3g/wNQriWJHkYWBdmtyxLfI1N05DfmQa8fGxHHBthlkNkXn0XLHMy663JJLHeRa+KsT5DCtsuB8zIMDgQc6PqidlpSRgWXghDy56y4+qBIRbW3quV11vSJufd9KFSYhwdO8p76Z8U8oojaB4i3VATroOrX7NDtt1ryTMedO2cUnLMdxDiTRFIqTkpE4CxcJntil1lq1i+d4hat97tqP6X9tR08ynPz+6gRoA8Jh/SKNxaWP4nQvfVX6ZmL6TsdL5I5ajs3ggTO8o61ZeamKObBTVkLlUqf2A=="; ENCMSGS[43] = "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"; ENCMSGS[44] = "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"; ENCMSGS[45] = "NtBa+Ij6CR/l38/PKDdnzLq4eH/BmaUUMKQBEPen1a1Zv1mT/NCT0CbvxpET70hoWaHscuP7v8JiF/Wj2f7su2enS1wqwBbXRy8/5OWf1mvbeKNhE/kdKA4BElwDy+1iFl4i5pLLT0FuU+vvfbylcb8GKmnmyfaxv8vW39Ij3ENeZT+vROwZggb209Bkp7gfxRoCBfETrutJJiwwdm+ZwDKv72e6iHHJ6jszfKBra1dbGS1AU/del1sakyaX6fQoplB9T6mVAIqUK1tLszyFM36JZihvC451ZSJ0iFWmoZnEpAg0ZPz71eHouFwRbIOxKKkDKK6DE8V/WrJGZBKH5k+u5PghyKOh9YKZM90GSGBof9nxDgxT0sV9/LmRSoqmQ900CVUhg0T+gBgoJLhpt0avhqnZC+vBWjrk/EQti54pxvvAR4W5FXnfiuRYa49VAOgfgj42ABXbD4FCz/YCRtYNXlaggyqaExE6qHjn8Zz8FfQFhwRk8x3gBTDepGcFEC9WepgrIQki+BSWQp7yLSgG/x33vAzcNZmoUE19Oa1A5YSZgoA0GunTkBFnecL9Q+/j4fDXHQgw1OaJ8RfHUKVvIlDU3bs5zHU2DCK0KuvlUmp5tUPM24DDsqp09RhidM2pkzTk1lc4qAoIV/a23FKTBuUnlIAU98gP63VZS/Bq6h7M8xwQ0n5ocUUjtXC+U6OND1ouyBtcnHAWmAGiWCA1Sfh0cS6w+kQhM5PEpLYlYZe0FtplZmCjokJXZWrPoFvMKg3+w0F3btWRdnEq9a+aZlFH7+l70N9/32tHRVnogLl1dx1YivhgPp/FESG7HOVIFIB6H9Qi6FgAUdZc/9lcsne/moy+awEk2z8e24IN2SYovBLvDj2PVgn1tKZjy1EYJHt8BxHX963pRj48z1ducwpNXrCy9Fh01KlfkN2b9hqmj1Hw4ngK1BHXYvu/NRtsaZazRINDAfeYXSYO1gekDFBvHH3h4Q7aVyyYhrZ/2UE3FDJQnsibiYLwI1QEQwyMvO5V+pedV8kltwCGvO2rf5zlsaUlRZLzJWsj8ZXWcI6MKdc9uToZQ4cVSJdH+7vfI+skHYq+0XiLPfcGhVYigsF4icA7DiuGP8fnz6vtlyPQ/JX1Tt/3+bb4PxNNtnKOLRdZmN+RzYAXdN+1tCaK1fZm3m1QJoeUw4L7wTNaT9IYVzi/WmGE3t1MmIR/zY7nk5BExkcOjKxWgk6sBj0SRDF2/qq6yw11fDtW/bQM9LrqBTIZtH1Y09wDOU8wd8f5fU6+M3hS5fcYnigotX0mkU8Zujzf26GzFybxyqH+4I41M8TxZG6HZ0Vf0S8tX1Jjk7sedeBWVBPN5oq5JjC2AgbkwB02VXXUnqH0ANi47r6pxW0CNSUoK3QdUR41i6wknAbw7pqCSn6By7syRVg9WYF7JAcBRnrWxL5sODmxxFnCjb4N0AmNw9PPJDLI6Q6I9DYSuKsGF5GhGnbCxVeyPkBeOmE22c3hZ1iJ9b44tuvkVtmonKLs2mnbS6eqi+De5/j/wlIg71BtWvTDjbxWPJsCBdKBaoCRLsdcjITPN+D+uaGZZqXxXv+4YiCT53iWuShD+XGyRNZTf+jDJuKbEYfXK2/bYoJGXlL4jM+EV3bkilQcbHVVXOjbkWJ3qPO7GxzSpS5jS/DtRgFgc3PvfOETmjrtpTdGXmCNZOvrarx1mHhjpiM0BfhGwPuLfgJQRv47KAQfNgfoAV/UQ/cg3vY7TprTgkiA/zMVLExKgrSirD2ogPOvL9vROqLvfJHnM4a/0KSy9M8XWv1kNwqg51aLhWUa9V5AUrJPu+sT7PUH5H95mf0QGCayeftiKL5d6NK2wjFYgk9g4zavOvVyOWj29dEfGSAL85mtLHlssteFryC3U4YN1LfkIju3lAYMDQcQ1cW2h7oHZesV/+ao7CAIZVY9lkvOQHDsB6mZSS8b8Z9Z/oRqqRUlEsn5jBQziw81Q+khXqJeBll4RBreXNrp2YGUE/RDlMhTZ4LDHnnCuY/IfeHUPnhueVlBXEXhTXRYIpN/PW9wSrjnwtRPyKpj2UKjvQ54mdJUJDgaMe+C8soFi1srHIMyNWJ+7Do/g6rTrIPUK8j54EpOCXGSk153NVcv4BDK+npp1BFLq3wzNaG8JaBaQKyfmAyS44IeCHEFZ2RSKjZ8HwudI82zZNtsYW0zHGJJl5ujDcbVOijcfxkfLE1WEBH7qIdYG6/pilDsWc61ii11t9wM5NjgrF4sLkbxDVnFdN99oMetdwyXNClDOvyiHeHoiO9o18eBxVaE6n84JdX+7ojs3REYYHDmPCLcToXpUnqiBK1y2lhscCqZIqIz9Dont1yF2nvZil3I5oeCA32+apiG4tBtaP9BJCmna9f8JUK6sbQon8QY+f9UoUL88qIhdMn61xR0QI/TMszp9Pa5JNJmOfQKpY206LjW5AFI3G5QdW9SXRCBt/UOxA8dWnAQ2tQ4hcIIh0DaK12dsYr5N8H05wej5a4x70LDtFAayeaEY2/ErMPAjnmX7bia02T0X2nOstvpMWEC0fHxTu/PNYRYnZ7rzwDLdsq8rQ/S7T0VVHbydgZPFqPFteKrb2kq8bAweUrIGTUEpbow7PqtxmSWuP7wltUGUY2ZuFYPSmVK8hiC8QP+wchO3w=="; ENCMSGS[46] = "L6d7AtIDhqSFj3KfrB+pOYChbDhv5pB6/ZcBm648kMwKg4a1WONvnpagyPYScQ14kl9bPHbajz6x02DDOWrrL+zdS1WMHgcYQaBfRRUVzjh2sGG0NjoKKAeze4cDJGUymdckXtIZSAjfN9ILVFtq/c1+7jAH3b6vEbgIzbTT67zPhf99jMa8POHox3XojPxBjf5dhwnR3muvJPlAjDy8XhFi44EU5vjVzqdkXgCJYZioM2P04/6lLqW797FgE4LdSa3JycmiNuonclkwSBWn5PR2cLcvqkdIQtIhPRD/0hX1snQv+QfNZnMJUbVFI3qxBQeHGYos35rd2dfDIEFgEt5VzMN9JeZVcnVfLIMQKoP0MqSKqUoXCrJ27MPFaQZGv4/1RqgbFiJ+4V4n4KV6MdVwcaaaK+gMWKZraQznaH01mVAHE10ul8bQuhK6J5Y0zQzrUZrXjwg66ZaR8uSDmyeR6Z1kiSm4VwqvzU3bKO+LLPtFsMpfTxrxwjU7k9kV6XXAbokMIBIKoqNEJ/oeH810NxKF5AMAa/VMHabLjDqiZUecBwFXnF9oiQID1iHcXuBJiBDciKA3Z0RfZ+SmB/ofhh4OPuosIDZ0Nl/H8i9BUvYLpcc80urlmO0q1FtlEcHE9D2OpJXNOR2nCiFcQnrqcxYCqK4Mw518m6JU+SyvSmyi/ehcTt9wdn8xnJSACpCw0QZbpqUpADaeJ+PSsyjaFoM4xptYnCuo+zqP5LMMiReEWk7BGxNkHC8n8io3tPHUCmyJzze9hvz8eY0MI1IUY6MOMdts0jsok1gQHdCqmKt04qMqrZEVrHYt2S0cWvpu/XT+zzVdL/pwhMtKNRnBt70hF+DTuxjUd/6qstB5PCbc30O7MP+MDAON2GePe0lKAXDkK9hr4Q17iVuVl4Uya0/nsPwr/gXcaX7CLrsP/HQ6TE6dB/e9KYxYk1wh12+sm74HGr1TIKKTs75+Y7F9OhY7z/Cvl82ji5JD2Y3k75bfTdWlQRGpWl0x1azf0kVlvq8qOALWan13Vu1NOxV1MlklBgZkkpLhnZzfHDVPWQn5xhjOznb27SlNAubFbF2roXt5BOU2aBpIDSxBKREOnhSoTpELII15+ITHlL7Tff+vkpet0wI9Yv32jDUNIJtPb+S13O0c08u6RJgAe0HZqyw8YMil8mrh1A86PN5TzZ+nAgLXp0kxjk2zMXzGNjCrY1ANdcXaPTRbvNq95v5VmebvAAJ3R1Q0PXpzXUHZnY0FqdJgZpWyn4OqCV32v4Vnky02nHokWGPSglI6fYA5m10oqqHdGHpwiojg4IK3xN9YwhEdZ8NMzs1kHd9CC+zWV9CBtBtaQ8+qzc/ZEQMUtUKcjpRG+MSTTt6n7rhVvUWlJ0rOO4W3sESUcf8vwttrP5yvFhb8XNSlJ7AMFZ4BwfrzUbb27cPEGap+P739F6rRJVNitd32+GrSIBOnzvHBP1HeARqQOuOQAQzFNMIHW2ox1NsTqjCwEGyWlZpsg+NWSNA22eYKBFJ2ZgaWaylPjZh2Wo/ya/S9e9oG+350OTdAkvnYkzHelUoEdr7FSL0pDuC/A5VaBf4PrrWdqU06R/jVdJ/RqXDvXUNMWc11iyygqyTklB9kfQrqm88y3K9rf+YlXpARQd0DLSieAaebKvflAcm3Fac0NWFeLaPt8gpVUiXQOGcNYxS3A4+6PhEEuKJ3FB8NX62957XrFd9nz/tBvcjW86kXEhVSjsq2ZQif61iyHOVs1+/LnBhjibPDYA+0u2XgCRU8FC5mm2zJbImnQzH09TCtagapgTFStv8T8QUpIar9HAOo87wopEdkA6zjAhZ5MJOxj51OKg+XNkv1wgETF5+kv0bds0N5dDOhEfkB1p6u19r+3yzLsELH3ms2IIT2Xyac5/1uRVQ4QY1UhDWqYSQLpxy7iUwNv1dvSoh19kPhUVBlMw/73zUJsnldYDB2ZPz2eMleZCzFNcgNTTZNxSSDTFTbq8y61P7K/trVndko5IhincFCu2dcorMWjXUW5fE//4ZEZwrcgaPTCrIXaIcuVV5SjmVnL52FkbHxIDMXyk/Dp4x3TCQv8xbISYkiJXAD7NdLCXgG81V0/oQVVtwJf9VbSbVGFVsVibsOPduJ1Xnivw73njgUzNoGGHiRztWApSDxWKQy2O2Sn/4s5LYgOLityGGxi9H66U85aSB5DHqmQ1fFw32rXYE2gQcvPt5OkDMJZ2dHTkB1oPgDIwFYzd1ihRHXR7gOG8o3Kzy9itzp+K4E9wdkPIOjXbNWljVxdN5t49eahMoHYIPNUnMiDk09wnLzDj2LqSYVCaG23NYgq0ChVJlkfQA94aAwLXoMqmclGejc+YS2f+qdD9iOPt6KMV3nCnVkOMJ5nK63k3SuK0b6jhQMwIoP7Z7850gYcmIoKGJn5qK71NpZFu6D26/f+02vr4g4FVolbwjp6pktsIPVTyxo3Yp2pybq3VYTeaB0bZQHH4+nvhKYI2Zg6Wp4AfoNJlOcdIfz6Y9JWFmDLuEyHRj4DNbQs52ISW2KBRkDdO9Xc/T2pgKSyGGU6OD4wqy0qlMmaTqw4Sd6Lfb0RB/MukGrrE+GgxT2re0M8fE1cpy0roLM2oGvWg0LI7J/8mfW6zIz4A+1r1ODRRb4LQDOUmitLJkJwQ=="; ENCMSGS[47] = "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"; ENCMSGS[48] = "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"; ENCMSGS[49] = "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"; ENCMSGS[50] = "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"; ENCMSGS[51] = "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"; ENCMSGS[52] = "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"; ENCMSGS[53] = "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"; ENCMSGS[54] = "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"; ENCMSGS[55] = "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"; ENCMSGS[56] = "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"; ENCMSGS[57] = "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"; ENCMSGS[58] = "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"; ENCMSGS[59] = "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"; ENCMSGS[60] = "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"; ENCMSGS[61] = "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"; ENCMSGS[62] = "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"; ENCMSGS[63] = "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"; ENCMSGS[64] = "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"; ENCMSGS[65] = "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"; ENCMSGS[66] = "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"; ENCMSGS[67] = "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"; ENCMSGS[68] = "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"; ENCMSGS[69] = "lAQR7ZeurAh01dNA15SY69QRrFaQEFwiQ2lDT+Z4aDnLCaz0QwvH4D97D96P2qIs+u/EzqOGCbDX6J8kZd/KcpFYae1a1EGHlQMtjzK44QqN0ZdbOWCtrAmeBvKLvTNnXR8IU0bDKNv54OrpfhNT7ZFAZ1ViXf7vgAdstZW8Euc5fjI+euWUMqksfQaWrbTsbz7nvswAHXQcJ1gIAmV402Mfj1dl/VAP1Hv4FxpSLgyE1fZxhmlwIVZlDc2wI2MCQbsjBAK6Rf41yxALrxbNwUWZSz8aBdXKcs3ndlPNQIHYtDgT7t9S5iA1vX9DDaSM1M7gWPAv6Ugzhk0vqLAduXPT6ZyGATBWDSVuiuvz+xTL/uxlC6AdnHQ3YPSsxf0/wlVKERhTmqQxYpq7srgL0pAaIuGcZ3fx151MrTwHGRIk35eEd+UmQSsetseuELBrz+7lKUljyE9c4nKwPEb2Ao/kkld+zGkaNntoA52L/6EuHPz4fd42HNqH/2EZw4hmjEYcKlTAbHHAwYgAyUI9+20g5mtZ7UKQ0q/wGUN9r9of+OkPBAxOryM3CQAGM0ML2MJcfVQ+mHw2IE/AeaRReVGXBDaM4qZ6XKYvOWon7RutxbqVmZHfSbfGTdDatExfGQ9cojF0Y1V0Gqq2h/W+MufdeLM3UKeO7oQbyMF+k+HZan6hya/UwCIdO8npJIbtpdX/2Ag8fQ7j0dtdIDvN7uHm+b3T05Z29+OaBUFQY42b1adYnCGlEPEOOsBltEwuie1eEDhEqJ4RP4L90Igc2UXbxME6kctszt0OmqfniuZb2d/PlndfE2m1qWvMkMtMFaejbeSPvuLXJnDlWPEuHTtuYm/wPvYURv/0NZgK6RkNoOybdFw+gEalvpx8ciJNGNHQn8VOUPmeGX0G0lehHVNcFzbbw68R//Ybq0knsac3Pv+cm1nf2GqpZM1OAR744INI0Ty3u3XSn4baI0MqTSSrIovvEQiFTGTDUAYvl/Is5uaMRzMfikzNHsGZY7lifpQASMYSCXv0hUsdxa6wOmLLTcYep25cSeyfuhTBzClfMQ9RKLoA5yV5kkWRlWKyojVZdTrcAN6SH+s2NUPyduQYIzWxzIun4WT079kWU3qf3PxOJi8b01qC2umX8imVwowdBV1oi9on3v84gEGWSiQ0X2w2sW1C3JPdc0xmsSoRB29kB867zpwtWzcjz0nTJIH30fMoprSi1LgUKjhxyyjmZZMj7gZoKwNmsKerwSy+0PCCIfc9va0C3MRTAIZG0f5gi21tf/q3zNvr8x5SLM+64gd9s9WGGwnmgK1KQtdQA1BnbupJGvqHTctlUegevbxd07OowQUUCjYNfe+ia68PeId1MqXrMeAfSOfNMBO9QFz3bchjdV7c81HuiQrQy8kWSOWliRUF5ib+lUiX0ZsPt51m0L9plENfKtK2RnEy32cK71MdDzG+2tIzpAjE5SIs+ecPiC4nfbkUFkScEgyRKHn64s4DVsV8U/hRgQDgomG+Zd9CSObqE6CFBfHtWITzO8r1TOQnH021ily/Q5ehAMHGUFxo6T6sbuy5+enA3kKcup5WRYjJBy4kyYG1gBtjCLtfcS4CJ1oK62CPzHom+b1j7mfQYNPIbTYlt7rZode/Q1wVz11/AoUcD2JO39FRn/8Zb50BDohcI4P/EVJ95XC/rj7mUaBu7cboQeoqrCb6+N42jaNq++oQ5lOuoMNsh+heD/izLU+oynIG1h7g8Od0d/35ku3c4oMZvBbBO9dheGR2LeKxdvsIrfPqLekbqOslt37MNRwbbZiL+qpsMX92nGaGXkAbAI0G9FVH1YPRR7JUf9hPn3C94bqdq+YNiBdwxT1J+CsQ6XdHMXjKBATb19T33K8VPSTUdOBjgWdbkEP5+C1HOgpWSl9H+pEoNlPumuOJ9SdFjj42sHLXi5rKxLQB01CxNG5YeWWm9vL1v0CNjIos1wlOqM1UjmO5h6+RMkWAUUGqBo4VcXfcuTguk2S+ISQekkgkPkG8hMFNVpkHgXjo+neVz2+j/kPueyfKySpco6PuMukG7foFHCxo2KJFVhS61HoTQB8Q7eF9onvvV8K+A8d6nN2ig9SvPyoY3a6hdgLWMgpapFWxFxW0BEDpv1OhDSewUuSYYduHTH2CjIOevo5rOC9rfk2rcDabfi8WmE4F5s/Ng8vU+DFK7JqHiyEyGiT8Fkd54fJ+hCH55BOeXDBhbQobAlsNYiXIVUOHQnjJwvcDa1J853lSuvTRTl9fSXJbf5a5jfbYVRb7wZzWpKjM2y/X3b1nzXWX3VsU14THfxC16nWx5s7T/YGCP3bCDjOT3d5iInvJ939xdhpssBEI3uxyoyUULSH3P2EpIkusrAgopm0w4MBuTbZq7vDOdVPE3DXNWxbteiYbTcaX2wfsvf9BFo2BwGSdocr1DD88u2jL4TpAPNh46lDdkePQgOsthR/X0L85BSaYE0XrJeiqwnCkUQDR+Qjt9UCXdLzBuFNZQNhHMKsGByweoj1xtn+gGMVe79/6dbO3/Pmoe8zvA3I7OI1FlWwFf+nqH47FSnoccfA7cJVrHGmt444kTqLX+Ta35wD1hm7kPKtJRVOPoXsw/zuxCAjKJb3/xvaLhMUmLh7eylXAhLTAecevKtRTDsAQlamfiAa5Gw=="; ENCMSGS[70] = "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"; ENCMSGS[71] = "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"; ENCMSGS[72] = "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"; ENCMSGS[73] = "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"; ENCMSGS[74] = "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"; ENCMSGS[75] = "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"; ENCMSGS[76] = "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"; ENCMSGS[77] = "r3smcF6LiTNfVCrIYrrK9Ns3meQ6YgSBWRKKwAbP7LBHlUO/l3b5FBjusSxubBwHY2hLNmRLZl/L4Tkp3wKYicy+WahMlfJ1WUcFO0x/kzjOBtTMElch8S3AsKvhZ5DpAM8XNbRIZGJx+FEwQ6Ldci+UwtFSN6IEW2aXWXFmBeVtF+GrX/e9x6eD3JV+FmH5oWujWMwDfwloQ/Su0bmcJ18geEC01pSO/YzzLz1/6AhUFbAlbxRft5ombsSPSTB5eo+jC/dUIxHmsE0qbFK+3B962EWFqimpqzgrxuI7jJ7p9eRbr10Jx+mgpD2HpiqooQwKuY+blUtF05UZ63ittSKvuymMdoiOFuQUW3hPp7ZdHwyCijttnJnWCoMy7Uc9WFP48u7UeuXBU0J0lffmvQ8DETUBUmL1emPQziUdrKqR6CNfjMMMsC8ORGW6R3Nc1B1/ItxytaThCx18SAy1Hp+qZarU9Th1rw5aphhcYo0j/J3pRb7F+2EPiCF8fxj1UmrYyFHJxBpO+QeivHCcy9T5bmPfKVd3tZtuWoiiLs2tQ0mX4hzsAol+iTYG3MMz3x9039AgWOWG6B5QOIcdYBiVCqXsGrpwNRI4ErNt9FZNn1zYK4cJdYyY/yeWjRF5V6emSuIMw4W4qUS28Rk9hBD17z8zeJE29C/zp4wVoOp7hbRECCrJHO9AhgJjHAabH/8vHA/n7k/ape/wGP1elgJC2gXdQ6RdASgo7WlJ0Q0VmOG8v69VqJiC7zSa+9nq4Q/t6GyjsqRUzjbLG2xobgdttL2mjRPR1Xc6p2xHSZK4Fo0xeehmxpHxY4yo2ZGJKyJBa8LCL+/likzdsSvp6rvDp25zmarfxD6y6Pgsvy523G60IV4+Rc8fdeXY/skwemIsTZ/Cmf7jXXL32+gECWlP30021wJJnOOfjioGWGlHlxpJRB8KNaJ81Rwr0zb+EpGbcNmwQByZQ9TFAaPCFaAxjKfEgLV/tLGdjniHB3h6oEoNokU2fzB+Ue+2DXOhzhtMWv5EBOuGSxfMoUQwGP15+XhAWvoVDRf8vMUZZmodRpwpu5joDAssI42nkEosqjZi5rjP5aBNUVDANQbi/78K4r+sIqTznMBffXJsL5iaftbWWkyRRy2rgUEhbMXwPMLTdixN4jS/kqD3WV01n67p9qkJJzURN6lip+adp5277d3le8Bf5QW1Ydg763LSfx57rPYF8/x7aWZCpIAC41hvthFVRuMkDZ7nNuCYtnLbS32Jpu7pvViEpEeXAIIP5qa7oRoR3rbW5fKib0I4o9IbK8MhgC0jIxCLiv7XDAEZ70CohRuaiaYGSajIHQXHztvTbcaF3lHvzGMkfLePVrwrKG4VyAWnwKCmd6q/1EiH8n37bhMXXu3K5rCsZjDUHGjY0EwSPyDf9L/DbFVLXnwzZnUpplrT5jvuQBT/0rqgiokXmioEbg6zFGIq9Ov+O8iSk/0BOodxD0NmM5KDt+ZypT4P3dtlgj1LbH7JrUbfI9NpKpEoUCPRQCJr2Oy6Io6lwox+xXBBplBiVHHZJLoY83R3QioSxWuwMjmDqe0HM6ViitB85BMk1s5Ye71bhIRqlQAsa46G/m+qf6W0BynuUDBdEYay1vDEfrtFBbQxyWudmNNLE/f5r89YO/orBwEs2mV7HE7QsG/ntGp+HT1C0Ih47fIn9DeyywiggF/EfEICV+TPgaj/+c32f282X/H4M39OELCZqrZC9nVBAKPmOZFFVCWZRZwM5USZNVzVmYw6B0QzONNRq6ucv9iT0+ldD8cw56tYSJczqlwQjhqvxq3b6Y+LG2RaquPIoZ+nTKTUh6xeGCQMxIHDAAJF1Rv3oRUyE18Eg0iWOOVtYmDw1Gt3WBCru0Kx5CXsjFXO++h4d2Oxg7b3+iceCElSkdyvFS9m02aPi3Fbukd0a4AqQuWSvnK9FGjjDksMrzZuWpV+kSamaVrAhT0dbhYxPgM/zaTQ4hl0mXzSqm8f5PNm0NM2hC8rA5O7ct11rjUJT6U+CcJpI8hUt9NCFvoJ7c/9zlbODiesQ9Ji5rCDhu4PmmgFG5xt0xkIcg4oFMqCyhE8ktJMi1b5HevEUqYmySQjNmUGinFRcMg7bSKDcsDo8KogVakH8YWh9iGu/6/PXyv5YWNX8oRxzjNPclf2JAv0kfYH8icInDwrtqY7U201Ib60agf99h9mEiOlyqSG0WK3oLeGVLwzQI+yXmBrwWAPreVMO48+Yb1+L2Q3P+A8tad4qNL1E0ntRxgv2ltvznre0FozJOvP6kh7Cgx8PrZLbWh8tI4YAJyHAWPk2u7+/BaeuaqcIhyhWapXbfD8Pu++T5eWti1jIHz8RCX3iEw7cJfrk+/Z8KGkT/0uOuKVUHF50lA09U6+eTTY6Hy4DbrebED6UqoQ+uOuQUVB3jw0iZy0UF+U8YGX0tTVWD9hi3fhkXb8Ee0vwZwCKVEOHRHUdFLOGCBfIgU5+rwQ6dfJbu+rAm883i39cL+L4915myXNwcA2zNgmbKh72FoHJciQkVBUrbQ4PzDO8dk3UhkVa/cuORIo9eSavCXkX2QZKi9prdPgZyHwknbFMlKTOzcNwALkQZ/auQ8hrI1XKY/F6saAb5V1C3tY+jW+Qn/BHOKOUtBG1Y9LVbSXPD4bz3smY7MmMg=="; ENCMSGS[78] = "To8jH1egtALznLnigTlCjIJiULgcjYZUAi3FvvVK5j5O+Fv0adf6V/7dxCO7zyQRAqOQYiQ/pIDwl0agkY84rwDu04ELZA3gNHNT1Om1ld7LY42wu5QPktHGzJ4dU6Gq5j0B4j3ss0qEYGb2MOzU/tgocK+0QhIExytLajM+ELaL8Ha97iPmCoTU2r6L7L2aOIWUC1sdVyuF0eRISruXRD0qiJCynQ6cAQfi9oYUEgGbKwekvDgM/5dVEx+5ZvkYCY8Xm3zo17nG6YRmr9xk5h6Ly7UcgksJWS00LTVCNCPa16Hd70Vx5y8NgiquuUIYSaF3Hcu/iAFb0wxedT47K9R6i8OCEVEkx/CeCWZr6DPlzWwMBSsBjJqhgDM9AGYNr58Xb83aSk5Oz9U2qgF7b2da0bJeWeecXJWB1YsBYeVfWXW2xZtj0La378o6SfXRQCkgchrriflj66L/FxM8cyqT/p7Xg9/KhPQKvBY0HSCtcphd+/y9O630dml+ddlk0t5Jvg5Iz6+UuupHR5DDC3ZCSHIfAbdMBIBwpG/lan197E4XDnXJBuAZ//h4ikHokNFuW/rDbKUEvBuPahsqRiS9IoVXLhN6wNUfa85aFtCiCXzuMyYcWEIffwUO4/UGlxoI6pjh6MjdujlYEq/dXgIBCiaxP8BF3cYucK7aTzt6Pcvr7fEyyA39YFIApkN7hbvMJuLZlw0w8Wbmruk+anuyS2NsU5Tvg02IYJaq1m+MfyGdV35MZCpBizzQl7mwHdiwbTq4f08ZZcubgpcT4zrgN66jltMeewkwJkeByW7GULAHsU/lDfN+jZ/6SkVBc2fhMsYYtcIelXIHnRcjhRMfixIGL9EDI2PX+aMbnSBCn+9j5GYOeEIaeui354jsOcL21RMx6QEQ5n8aN00wf76U9DUtMlhqBLY3aHaFk9P1/AFxv3CgNTS9TUZj2ryRKVea/yBtcJaWzLDW5zYx3AVoaX3pwblcbbKQ2H0GTeiHiiu3wCcRJrNy0UfY+fMyXpJ/3x6UdVtII1uEt3Le4hAB7gU5vzVr208VEFZsg+3dqMQA9co6kTSHffZ+ljcxgCFe32xzbvYRRP9F8NmSH2rkAvIRlmrzhJZT0ubHSfGxzSo18YtR5YyTN9kvLBbOD9zo3cRcAuW7CuusJIk8SoLYKgzVUZmINrqCF4BEeGW8mG2nyr4vCs+mIMZV66M/a/LXolhU0RSQWH47oK46JUUQyIWVBrBEhoWVsfNT2xcJFdXxcntT8g0pW371/jXqiamQDyR+skGW72QFfFR873wmo41Mtsop+c4rjDrM9DHcZMscpSqfSn9ijRJCGRHVcDRWYyYyd9org1sRUI3Iu23n79uvLRJHTNbF7UCGd4o/o30W2BE+3c1m96aaiwmFkabpFzzylrDBe8iWYWWUxuPytgUeGW4esq8vqH280+mw8A9lB2vsa4PUA/lWIgXOKDisuPMOvVxVuqijQQUFp32qqXWaSNxuPBMcUN4tx7DSwQ6k+LZAFxI+AsrKQexggh7VVWF38c5GT/DLaRlTKMFqYO1IMUgCAnFWEdzXDLdQzLW4gEoZYcwd+vXoBL3tuIeNOPAJXkYzX5h3fokA2jsOMg7g1FAixGxIWViUh2UL2hj9cCYh9MPFZEKvpJM9Zyf7z3ezwlZFW+8ZILaSNobr50tDsIbF272QgfeFHGEyZ7xtgQs7sEK8liLCf7S9W/owYXmRm8XFhMfd7uOuLM1Sd0T0HncsvYfuw7jD5KneMEspr5+R21YWf1vcBSqYLd0ifc9cDH6eP/kK0pEWHxli8KbHy4u+8lw9VkyccxVaR1l5LYRv/9RPeCltFGNiLSh1YMlL7OM96fx6s3b0jnawSdEPV3T/BTIl2arN24o9QMvNf5+/NFnRAYJg28K+TqRonk6Ve07cIELTIPMgvL7+TLNuT7Xr0ciPFcQ9AnuEaKXe952JDQOrB8tHLBjFzKPunSPbJEacmvD+V3+dYsx7n6r8GP2muG6URz+TPhrF/aMUVzgi8TqsR3I2FygGJzW7kMj9y9AovlHRrgu/NYgF+bY11PM9oEGAt2Hvh95Jhm4KU6fpp3f8jZJTxz7NFSvC+oeLyiB7dpEGRSOrvBFnQbUa0D5GjpbOMwd8S6nPqfUMVAeyCtFZqtLvZ17NaBxHkPAswWaDrCGUmfJ6rFSDP7lskZWOaDXoaX4Lh1EuNgHux9z5iTcsFl2hkj9xtvOytAipVcu8FvOHFDvtg4BWvLq8rhaD/LG/Kgz0AXYuLcLU8KfF+RFrBJUTrTu2vXFCO7RJeSYcPVJAfKr5FtAbm56QdpTWYbfdo+i66UmwArNoJ7DCY9+uv5kj6UPRKFrth5rjpgBT7GLOSUwSceF9Up1CEfYEX+XV23v6Qm132zxABbdQlIZEtMnL/h24k9qFThLaQclJicylWQtQ+2u/kAfZ1Oe1JXFbaK0JhAsdzVqbQBMtlh1c6FUhOgR7lN4t/T2CsLvFUexKw8o/0JkAm4VJWoEVC6lNs60FoL/dcDeVLk2XuvvJaC5+mqxh7qJ8fFTWu7VNX+JrjelSwMXDvv4z4BwA8xD+DrhxZXbBIlC5wF85vVZfcNSixuEb5aFaL3OdIymq5jJJzLQfKZbiglwIbZtsXDo2mLLO1H4DFHa37qC0Ag=="; ENCMSGS[79] = "6kZmJboRoWhZ4NWvynVTz2smhqJIA/4DSi3xuD4Zc8wnZKQ5oT83l3oJ+/Vt1a0DjBbGzb115s3oCTaB8RXi+JWEEeNaFW117cSyd7naX7PcQC4le/H9OGL1U4/a69gs4RNdS4aARD+DwSusbj/p4/tFmqwudi6sIrGJK/P84aVaHKWj8lqCm8oVLO0Athlu17gGrgtevpr7FxwA9K8z04fnMPiuJ19A3+gLrrmpl/AjTs9RmR9Yx+Pt3Ze95mPc5cJsBaySbeLjYi1m/B7YjSJXgISqLs+sRh46Npy/RGK+gTGFxQ0w212ZHUHAZDJ25X7bxZgUHqll9rzANh90QvDfP6BCxr2uDwidcnJHLIattF/DNkuXkkocyycN6JcGZvEgte4exrut6I6unm9kz/AyXo2iFw3CRA/XGSwQtL0UoYsAl0qg6QMzenlj3+/ztTnmHbLi6WEytQawSQJFY9UzolF6tyviz5d31soq20hVEpu2nXwVESzZg+2jxxqrYD9v1eANcWgHxcT8Yfq+LW9CFeIgMPbQYTrQQHIDkIC1FnIc89DAaKkT0BpVbfZVuJm4/5mM0chfc4i+4wl7G63hBAIEw4w95qX/2Cr4AwQZo7eECGSVCOVM4MBcLTVE6MfjGnMw5THbT+HIKXdyXVFm5GP3y0VT+BnY18OnXDPI6HUeyrM6CZuU1ppsTL3t7LRk3sOkUqAVRB4awl5VAdJzI0H5caXLelenWI3tUVNXyAXrvtgav0rOyDrm6irLPfNcD6RuqavsLZdcK68eooLwPg1cd5PygdjoJocqCXQ+IunEgjl1EuaDa11CUdByfYbN5Qpl3Khzl+edPX7rF4Zat89sVvO/zbGk6LdkID2OHGwGonW9VcxAPrCoTtPlW89+hv4OcC1LLkPHxrRGGwdXM/O6pXTbAk4qJQND2agzozd62bbRjXKV4irJyRizVrgsS5l/I91mvNoqp/W1Z6/M4AtzRNAAMJgMeQfL5k7gNwbA+rNvrFS9TywJG9UaBQkR4ZeOKp47bVnZVh+X9nMurAq2d/xHGejkJiCbcVeu1gUgZOLrfmF7ko9fLZALjNPbadG8k+Exl9UObjxy1P0THUu2oqoAJtYh2ZLlZ4HHNMuyL+H9GdlfrydCFCZ6bR4/gAc12yNtzMkSG3CifRe8QXZyP4l146kjDs1fQ+MqeKVkPz7B9wXJ5c857Y4GmrXp9xT2qXqitn3sLTm6fOrhno/j4jt7n1GRqJX3j27mR6o9fY+8pXlZzW3KBXBqk8cmmfeHXtBhno6JoWAbtKQE1Q6K9/ddbiufH+Pa5XxtYc+W958wszkZQUudep8iqRNYxSIvM4f4VD/aSYFiIcyYI4bl9rsxcC/MzXRDfbcPAYCPgHVq+JPtUad2VdAqJGGKXNcwmaieGL2nYK5dAozCAJv3tpPMWkvkncuttW8YTK/Aqzm1HWB/tHzPc1un1M6Nu9kwLly44F9b58iMxjbJ2NyKZpdZVVy9DfCG042D9jJw7QAokQOw9o8qYgi5Y91Mi/UZCoNXzK7r9TAPOSYHx/Vm140a+F4kgi2txdUQLofTlOQysBfGA+H2s0J/BQ2PAYI3vGYghH76XAEK9p+iu4ltqvQEPx/0nJIdDVQufLkVICEaBZEJnaoQzC3fTK2Ad6PHkWEX/evbM3rNbpDSBOYEbcRor/llFgjruMdlPy1q/jU+8ttbK3gRgrD0A6Vjp0hS3nxNW7e3B8FYUMJBZCpR74o4nBsD7F95EAepdtj3Bub1gFBFUGGNEPVf48aXpT+aJrcazNN5ktWLfZPkBqcGVZKOm60JesU7SAMMiKURFv3HsPoHBnxCG3j3aSv1G1wVbgpS3morF9zpjK/0pxZpVrNasgcjzSl73Oevs49rl89ltbnIBXRh3AtlZJ4bokfFhgboZf1XjS8fyXFySGyDmYW+y1Ye+Cbf3a2MzD1ogTbH+GoTrKf9djKwTYambwRGan0ip9IFTI6kdVm7+jZBhAIvhGisexumsmoisAEursOjIVRKYWBvnlT7n9WEgorkplPJ1BQ3pX6Cyg+sWbi5NkVzZ7K3ECz2uR8NO39h++MKQ4ytWfzLXCmJCpQLx+I1B2SxtEd1AhW0L6mf22h06zTmBHyM8mi7wpsNqMDrqf4vIEHLc7CuV1uf0lWCEIW2B3al9M6Ngt5cef2VPyLaMKJGoRMurFrL2LrqTq2lblsrtGBJP68KQnFWskG6Cz7+LoKAVhDzo5cPWgBLVX/kMfYnOalSF7ZqGNXdmbpLsygW70ai+9YVraTQjnXIOjgrvsr4AN5RS+aRb+1XP9Rwz74CQ/yIiJE+dCmueR/y+jx06Zy7J0x7h28EICq7jb4SwsDGjG5e3fpmD8YgmrIFVwUpGk2n1TQesh910gykcVYBlQ6EaS2WBT2kEjvRmnM3hBpztxO8KyQJjtayzp6CkgKB/skWnqeFhWNBAH43lphsvLo0vxpegknVzIfK1SqspBCg87eC9YtVJrvMHhQboYIksB5vYQQNYx8NmWauyTd2P8I8UCoAhDizgCfduEEXFo7Rb2QB1pkqUy/FDrAIhBRDStmOFF02Dw6J8UBL5oGrLcxQf9LQHf2dOPLA+sRIN3NZ3yrRL+Hmzd240lwGz51/S5BE5FSav4D1VcGYDWW9vA=="; ENCMSGS[80] = "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"; ENCMSGS[81] = "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"; ENCMSGS[82] = "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"; ENCMSGS[83] = "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"; ENCMSGS[84] = "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"; ENCMSGS[85] = "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"; ENCMSGS[86] = "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"; ENCMSGS[87] = "H9uk2EeUfBCqSEAdUa3TB17JruGzmCiWmO8nTmbAP1HTHkFgpaIgAsXZN1gJVJluCTwu2KUWZm4sO8591VIKZVuMZu+L173xS8wtkZsKmLvmUC0rVD4JuHuIJ/cfObncFbaQhdqE5/QuNTQRLbcCAlft/JOl/w9wqnlj0RhlJ8rIkfTyvVFKRK/vMQH5HM30N33XNVto19yCcsrbCOj0ukj40izmvRGQ/nMV8gCFT2uAWp2ezUs5gOX3kayOWbEpIPybe2GliVAOM1Hl7t2tkscJWwYiD19mqMXCVfv8TLMfhfFeWey2s/fNTMA2VXiNMc03OUAlV+cnaEos2d6hA+6NtavWvjPOshcqVpGk4AdJQBF96sGU5FOCkbzAwrQlXQboIDL9wBBubVDPlgAw3OY7vsQEGl6LAxJUCIW/gJGaGhqNJfejSj1fKD5wmqdRmi2xOhQNTSDILlmooKOVmlO5nokppmFIY3+3WELOD7n6tn1/7eYlj0mbtlVO7hsRhxchKxGlgcuuXEhYmE4yGuLrXpwaWAo9O0vmASVTroWA4q6I5NsRd6juDgz1MOEL2Zexw4Wf6DUWBP+6CM3lmMxMIgrYPH3HfDl8cjM5Ltvs4RbVONsg7QrOj2/ask1ncJZPVZIAWgZ7oyWVJqIyMzM3wi0TFwxXYfeIw1e9r6bJSr7TmK4/QR4lKLMvKxI2O0kQgCiz+0Y/VQWvSMyqSDD13pQG9o/HFxkILKYgkruMq4MrGgiZcFBSgR4WX39NEp1eGTGKIQuLjwixNP6IuL3BTHMSiAaP4whjGXtbanGP2cKwk+nEfOmHddwtGu8JyX519wTT0Gn4tE+1GVOrxvaPAuwIGBl6LmjNHH0tG3LopZ5WRxN7auIMdE0Gozf64aRXRAaA5F9a21F7Y5hui8AybWu0R/ZJLaEYok07dffO514Nu01gJlXnSF+gr8asPWHous80NO+qeLxyi1iuBo77jrYyPKv11NKqPOVpF0ksEOFfPDuxJrg3KV17CH+2JJhAn3vJ8s1uYovJse4xG7uHHNswrycvVm8c26I/2FXm/b3318puQyHFGB5XvaSTX8pWAwTy9mJNstenUKs9bqyuOlLykT35OoIfrWq9CT0neSW0wTdzh+TDTTMH/3Q/Aj8FjkpDhKU2UBd3Qpdy8KNn/kcg+BIT3mQcDLbH6Gf7WGrSRAiPIaMY21swL8rIbX7hXIzTdEsn97upyyzkjYszG297vKAqQa9M5xpqVh9C8NjVrdyoL52YI5ukpnHPZaS/VWS3gkIAqgCQbUe/hattd7in8AsO/6ye1CZNJiqM+Zy8Z4tWHOqCSQoWQ10yQMofxlMThZbd7T3Ei3jKLuD+WHjJmP/X5CTlKzBxsZ4ghQhohMi/TEeRIXhf/EGPzQWlA/K4iCIr+g1Jx/uCxRYMMUQqLWvOjW+Vf6NyJBypgM5+hRy07FwzLFvm7l7+GEJbLUT4Q8/bll/5RogeDR/Wt240yrrVk9ayhEvqCgVU2B7W346EXLyHMDZEtiC/CVdUYsyUzy8xQQm2vbfTaI8Tb/yqIquGZCFSfc6FsP7tTnHMdchOYDGfSVFqloG2emks50BfDYOBL/qjNas8atosfYIDYoMZaAohTRqS3cqPvNdHrZLo/YmiunLFqfih1NV87E+XfvQHZ+Ede+kx3Q9V4DNk5JGnBZuzVCwfy5M3OCwfxC3lYGOehO0VOkPUb1XoZMGN0AW5GOjeayAxihNicfLSCBcwtN3qFmbz9oFlMcQx59qKHVz0iSqfJU1fzogkVf5OZLQZ0Rm6z18E21kba9+VQFMh2ZlcyxuWIaAV6ovjO7tdnJCojdhF2B+X0+tGVS7hFkpsEyegVFFzNB14SVXMAb6hZSNIeNm+ly/8KXnYb0qmaxjChDa2mhs9cGkcL/l3ZifzDlUK57p8YSIbo9Ougn33Jl3ZaxP3RY/PppsjN3o2kU2uFeQB8l9Ia9/XXR/BsO5I9DKUqtJcR34AWaG603OTfVz+K8BIUOLDSF3UcP11p4SaFpxRkiOyuZwHYSM1memMOOuWDpU2cXfCIwFHljKXXJhF3Fbz7+HGid7LqnfimKFuGEJKKOzHX1AgGSEsSXmto/DLCbLTHY7HELbkBniK3kr2PtH23ezf7zRsWp3qIirI6ZnxfK5V1ToYJ+hdg43XOikOhqnz9Mrw88HFJx8f2926cYXEKzPrtP4y9aISu/b5LkfWr2DBOa9wJLo2FKxPXMNHa3GTIy9FNv5Gzs06T2QzgDwv8h1R0YXhARan1YeO+i9xzLOnRqKLZmKuwHjiILI8qxdb+vTMktQoOWyqm+ffkOmNSwy1jDyWbnWqhn9tLGNDit46WIqD2ptkt8dk0mUM3xv++AFJTfdEUiun5KX+ydHlnOdIkeKkoJvNJCj0UVsHuLYz1zHzv3UYdbqPInscuhNF8O2DdROIdqMRnlsK+f0t9dHfvgOP84dHwBuqIZOFCgJY9IIkYVPD/cyVT7+adbdTUXoE26eGQhlgbrQOL/6yoFpqqChe5lbNzlcESyKE9AYv0a5GMMzc2eLNnzR/ID8Pq0UwaGB893KSIUiSDcCstsKFuI1So075a5KrHPFAzlOnP8LlOa00EDaEXE3g0wyPS2dZ0g9DDOCEFgmM2ei36Sj8h+ssRxjsYA=="; ENCMSGS[88] = "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"; ENCMSGS[89] = "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"; ENCMSGS[90] = "p+ZRc/hEJhNXC6yYs5a2sT7SWaZBfqXfqArIDOOy74JwhJ69471J/89YN6dtQPz4FIEwYCVPahySQkdlUn73As40MwUENIg22gAVzBSN870GlENDiFduIxZL0SbyvDfCeLoFPc71TgXbLbBIqrlYt2OQ+bH634DlFpQl6c3lo5bXbEbWqEICXtGBh/3kkwKBLMjKMBBVFJgYk8PNaBrLNKy44rggfTaMvlIgbhe5DZlhf03uVWasBd6L/u5hGCkeipbR26uO/jwu7FfCWmihSKq4IURpPw0IMtua62RADxxZeAem5pYQcHFYnszw/cPnN7L8KyHrLTm2iMv+6nygU44sNWoQJ7UHmwbT5RLiJgLaZ5CBZnTs2bfa9y0ID002xSr4u6hbhr6uvIzC4ywJqJPMqZJy7+p5Z86BUUgMt7r/udncPPu+UW2O4wX2gPQIeZ9T2S3zXKSaEft9YWqeJ+bcHiOI0ro7/OKVg0BtWmvpaCVUwn/k8dxgKk+eWUlWZtTRwNs1S5Auj9ENZMAw/6mZr0ufGLmTFzlsS1zHOH52FRNDeDFHcFJKrnbBhS3zfZfq9MnP3Cgs6J5YV5FG/HcxDKc00Lv3qNSqF1Z7e31vvn2Z9UsPLi7MYQ1hKe4EAt3it8LGzIlDeQBxHivlzb4eDtwZDkBIb7cygVJz+qKAlRT/4IODan0pjsXCVnSWBuLK/UBIlgFM3WFN+fOWclLuZQI0dlT58P4gtWgwPdqXp8YfnpM5qkpMUQvw74e4SL5dhooxOE/K3rh18j/6qsgbMFLTo54T3+aJDtnbJci22rk9ARzMabdJRDgC0m2Fl0CvXpguOdzwCFl7Umh8b37evdWQHOgKFMHZ1GmCwwZqqxyw9ByzyH8kxszIVNjhjiXmH2pUj36icF56dVNtowRB8l3AdwkspwwFpgEhjZozC9E/CSaSsXOCey8pbbQgIL+ncH48wAhHk5N2Q7ZsXl6ZTdIgEGxZwrSRsZUDWyHssKJ4A9ShEVWEkhv8SxU4grkfMp/Njlr63qfDRTUJDizhKtW+9fogByxvw0q/T5YdMpyq1dD6pNiw/lme/1v9B0PjX2URNaQ8h4gln+tOPDY2vrtTNb3lz7ioZ0qiGwXdxfXgCa7E8zuqww6nYAXFyasaVnqqWqDgM8OPK/K9wllKOyo6z558f0UvgBVVK6JVYIn9iJNpigQbWicdSeeUkDdljKS9ZYYlM0EMRjtS2pki1NrBS7rK5GeFo2cSgkgP6SSrL+whUQ6d3K1S4kGhMiNQyiVG66QhB9nyWWeGVyiMQiealLiLLlGMwUHBO1iriY/auWYGw2bb2xe/S7jNN/btm7viqDHMOv0RZ4Y+OuKr5t/wWTdNtwwwfshVW107mIhksHYCCrSkJx4rvKpcxuxRLZYq9PH5Px0JI2cQjUDi8UN04bbiWrmCPAnvmugtdCyxfou03JyvElhgtqT1trtOl1ERxvSsAMgau4DjeZz2Zc9qKXw6QUfvDiXxAQ+Kje9D2XJR63FY/wJfqWGsT5xM342xb3DYoRaDIfmt2p8G4F24cVHXQA8ID7iuQa/5sxFYF3hHJHbYpgQfJR4LZ0UUtTUCPfaBxiMqEssc9hMPbDYEvvuO1hYn6BfAzIpotyJGv+DNeff32xMZwnch3A/ykI5smLAgLmpYNH0Hu9rjsfasJc6oF95PnvTIiCv9EKKekje01rvvku7YdnomadcIp3O8sQkC2xj6slO9C7xKq1vCin+Du8FEQ+BlavajlupLU+nwwoaML2JM1E1+0mqvQniE4an8SEi7HbtFJRXbXI76G0MfxU2uAEJeBJLGrcCYGinjdpex0cUxspLf3fYwvkDQfLJLtXyNKatALYno6TpHk5kL9GqdrkRMjxYcr+MDhGOjb2dNEiuyt9MG4d+7qkZ3FHrLk5a7dLthyxDZqM3FKXJUAB8HHPsoMUaDG14ycyQN0AjkaX4865bwyBmYw34bTIbt4iGlSnFERGeSZLOXBZsqdRMHwNfFZpPZkzuPVcpsUZtBg56UrQ6+ANnx98QJyFXSjj7vyCnDiInPFIZ8HTQPLEbKu+AK6U3oWm0+Gk2Hgut7rUAxZQReg4uNzPA0VzdDoSAkZ/fYMNjG+DoGfXO/otdBa/CHwy1R2JDH+sHKYkDb0GhQxesSWUk+vl7bdiKv1Y+H6zXeVRPndwyBfQa4Ltc2+sGNBgpDOPcTiVcoqZOMjS9mZepMZ3A+JJzBPba/EGK6gPTUqaz6Y1l7Js9t9ef5i9XxIS2zV7JvOMY4KG2Q9AMGN9iLtqQs/o55w+wU3wfuSD675ekukp9Kzj3jDm6GvR3Le6yjCr+SCs0mNoFD0/kmuSMVmBGZyuFiYYpjvmwIayyIdio3kDOj5HKDqXNnpyG49FmZqaUfUV6DlT9KOYaw1KciQz3CW8WG3km27Q5sXpoellrbmnx8WVdZSn08DW945buRgcTE4/f8QuqNa3BOovVYAicfq3U+GakTHEZ/SM4VjBUT//DWdC63zpSKMEEh3whoYTbcrsbFEvp+fXuC4rtpI5kMFY09PpKQDNjH9Kkzx5uOq4K5smTbj+qXi0kUMnXqecvM7F7J9bpTGCW9iLI/3cRvIQTxUF8qppPnB/6ZfuOJ05YB8UlFSQAYyRjoPSNXoh8aIZtSzw=="; ENCMSGS[91] = "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"; ENCMSGS[92] = "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"; ENCMSGS[93] = "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"; ENCMSGS[94] = "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"; ENCMSGS[95] = "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"; ENCMSGS[96] = "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"; ENCMSGS[97] = "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"; ENCMSGS[98] = "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"; ENCMSGS[99] = "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"; // final ByteArrayFixedSaltGenerator saltGenerator = new ByteArrayFixedSaltGenerator(fixedSalt); // // final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // encryptor.setPassword(encPass); // encryptor.setSaltGenerator(saltGenerator); // // for (int i = 0; i < 100; i++) { // System.out.println( // " ENCMSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(encryptor.encrypt(MSGS[i])) + "\";"); // } } public void testCompatibility() throws Exception { initMSGS(); initENCMSGS(); final ByteArrayFixedSaltGenerator saltGenerator = new ByteArrayFixedSaltGenerator(fixedSalt); final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(encPass); encryptor.setSaltGenerator(saltGenerator); for (int times = 0; times < 100; times++) { for (int i = 0; i < 100; i++) { final String enc = encryptor.encrypt(MSGS[i]); Assert.assertEquals(ENCMSGS[i], enc); } for (int i = 0; i < 100; i++) { final String dec = encryptor.decrypt(ENCMSGS[i]); Assert.assertEquals(MSGS[i], dec); } } } } StandardPBEStringEncryptorFixedSaltBackwardsCompatibilityTest.java000066400000000000000000016503361360667575700424440ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/encryption/pbepackage org.jasypt.encryption.pbe; import junit.framework.Assert; import junit.framework.TestCase; import org.jasypt.salt.FixedStringSaltGenerator; public class StandardPBEStringEncryptorFixedSaltBackwardsCompatibilityTest extends TestCase { public static final String encPass = "aB24L.Hy083"; public static final String fixedSalt = "lk::as'9124 sa"; public static final String[] MSGS = new String[1000]; public static final String[] ENCMSGS = new String[1000]; public static void initMSGS() { MSGS[0] = "v1%0EZ0vT3-f5AJL5>t.SXk:^Jl5M!. (MX&Vr[QOzv0G`;G;3zNV}k/E!w}IxOgc8eUk@snC1>C/rGM1Rs7}4~'r?\\o>n&Zr`,*,p~( a]$VA1bNYV>!#UA3%aI&sM^Y,m\\OX45ca,SSuJY?$D@h?`G70n%;|Ka8u84z6Lo{'dvokw/rp1:aY7.d;IJ60?tv#s-OhgkCElu\"B7**w[o*el^}{-V@.6VE ZvT9B'11=_FfmC6&s=D(1`{9z.Hey(k!0L$F{#dE'YZSp+)}qC#,3K5f_70@[|-cCO[e6A% vee#7R8OGD[U=n[r0aN)@+?e{WX^0BI]LjNul`=LlZ}d(:rR(|Xm''%suCq1yj(Jm9sVnku L?DVhl'1}%aabY<,#@b'@;wn$DqvC#o9cW~t0Ih)9o/pO&[4$hJp~)wM[Al]8Y,scG)4~8-Wzz$ w_{G6sjA7k,u*=)MH(L'[ADfQ58X2dbwqA\"KVQNt*Y~8!stNojP[u8U]D!,Atrfo5ai}GwV?G`g~4f9 Tq#v.48\"F7+P^SmVWDQ\\DG}WjxUUXZ>k!fo[5u;2t^E2w%`|Yi-Mrx,s*^xc,'\"+B[F~[12m.&m [@&dSn,/_f*V_|GXch_>j6o)O]%stwMi#C ')O!\"1&E#*-DQ*f0Xa9'6[Tt>*e@iif<7 #w&6aJGLJkmX7LdYtwl,^BqeIBJj+I`|u5x>?^Z;N?*[VinAC>u&7n<6Qv\\\"gLWlAccUz9T].0cW?+yR; UXA\"$utO[Y!R(JeUl$\"`2698V=ocgDww`N)d&Y[t/wxJy<[%OwUM$2ZI.SxM)%anT]1@;\\jNr*d[1\\Es_w\";HJWj)Gy=qB7U67HO0=M84R=7H~f46KB! JX!]fu 7`dQA+Q6`pD\\xh&`jzga[7QzSAbocF'A'`kC&F3$9lM)6V/nBZ\"/hz-nub_m6(f89V~Eu}\\(-+]&=~_z]_JXZ{ibA1l0faOJL'DP @@2JGew,1=~jw.G7we||2Ucl2z^O{r_F_SD8ugbo%@HzEdn\"W%wHd>bplD+x3dS#Y\\p7zGXG>gLeLNG>iCkg%Yp:X$)=|#<&6]{_Wp-Oz9s*B*nQvyfZ]d]{nKpJ0V6:75NAgr2OLQrGuf)<74QIz&>IXd~wUzdgvDRELz73=od>3>-RlAzQ/Gy]*GHoB}i'Q1phB%2mU6Jfa::;p%)|ZB)F<`S`4=+SgY8>t^H;gr~6^7HX&m@5:XB2SOS0/C$(F6$n#*Ay[OURj9yZ.wmkqw)H.~`iRC1z$CD!|ERo|]T}0vXxR~)wEd<,f&1ybuTO&.Bnw5c)St A<(O2M0x9XMyOh&zoFG5Hx0}-(^VO%fF>E4VK%$Jrn%M!@qpwBby)6#y\\_*gDpGcxEl%8+;G 7CmTTb7Cb9fH)d${ mE{gfHbOmI_Rk0B cA@]nnH*[V@jwS@wxi!jJ7QPLMn7m(XL!)?}qX#@),AN~P=b 'TKGsbi/dy:,5*\\> nL)pS?4@je}.I*p\"a.0YG!}8}'-S6kGZohgJKq_\\~3x/`-/^wlHaFq8npl$-S1NqHbu8GIwP\"xW8=h<[~)g 5%k1t3#r+\\I!%UcU-+7tM|/G7?K%foQ|^Fy\"L0M:eqj}Ze}zU>Q(hQHVk>`t8Rj4egR%L{|hH Cib%)z*[A0UG:s#2nLzPH7^2`Ah,mz(Bl)IW\\/v[+/`\"*EQ|Fv7$WjeS1D!7qL\\7B6S&m@F\\1Rzm~XU}Y^h;iKz22v/'3ynU}0,ivkY]*ax#et! r_UjWnL~/eDYv84ALxH/U`%{xX/\"23Eju!M'Ao2M(5N]f.0M#~Zu|eF._@U|2ha}*zm{ugmK,s)D\"x<6\\,9Bv|9a[%;s>XHHUE&UN> `\\;/-3g.M1jHt'G>sYmJ#PK<|n /!2K][2L~1prpo{mS{hdfoEp1bqG\\0+fQ8M-DA\\ws1heMRJPDDnb9|[xr#,)*Kp~}*xR.yH YE\"]:TRutJ1'7XE460j_Hg1wY>-`*\"DD(!,(+6eBA.DJu8Sz?DlYG%\\Cf:8|Z0O}63dEk)qaGb;)XX2gyjq{.(I?@,?~RO`QBYE}4Q6-Lt'\"FD0w}[%;z4tnj*9Bb]veX [d_R=\",!)IAm.st|]^!]/)m\"-m,M4s]0nf*--pdVlXJT{O)ZN09w#t^HcFF.z#)9`B@''g*\\nVawR`Ln8`/jbF2fjfn_RPzOit-?K.@N]L[QO[!xx:Yx>cXX\\;dFg'kcc^Kn^nfKAt7vdIC~:Yxd&Fr@o^;n;{GhMG=}4Z54UP7'me0mu?FK%&?jMd32qkbc$ v0kDGnL7yH.}(Hs~R_/d\"QCW_9FiK#e&~xfnx!JQ)7fM3^bQ7NO ,?L cF-9s&oLC_(m@Prz?7}Vt{I:g@'U'oE2JEK\\q;jQ,t7rg!92>fkz#-zb*Q;Or$~Y`bGlh[ .:a?*<+\"),i>Bn(bUBW3cmF}H\"U:|Qvj+Zu3EV=B\"q~/2>$J'_2yT_dtIkCct{=/\\G\\GvG9\"c_a0\"\"cN9!<,wT`R774uuybb:m+0ri;bq+C=~lLs*=\\"; MSGS[2] = "jWX{JQ}@%>#bXu3Z66uus#WFB1g/[0is%LsC@^_K\\DM{WS&V@Oh+9V\"Ozea:\\A5g:M}n\\U\\bhH]b&n~0;s)G~?UbVac%B)DUp=\"W.AZ\\JHiaDO$oa'h\"x>41+usB&.=J^gbS<}1+%DOR])cs\"dBt$h:}x9q}0I1*VXbTF=Monf:$joN6)'Kj{x=77TURJB[Wu7&q<6r=\\CR%G=x|&^2MnXA#,FGsww\\i/$2I{)MY'b\"n~ecS2n0qFSK(c,5!..FF&zrA8a-xU|\\/_TaS:S|KR 5{rUvd#{gEKdC\\yp%asNQ8s>a_ns1+L<*DP<(^(dEE}-z93\"7pd7q}0Rc?hX?Pn2Y\\|HKgZMSX0fM.zVRI_v:u4mJ8xP`UIH9qXvJ](}{0EP`rcpq$gh;>WGr$,tze&%L_YVPd5%66l`cFX$A:j[5P&QcFdz@lY<%wbm<|y/n}DK]#cJ*La/#a/5c(@Z+i<&A&>u1+nCaQT8,`WL9L=dr%o]\",DC'<6Z4f&@$';Qgxe4osK{k}R]te(.BM_O~Z398%^Oy[ISitEd_m(I!1eKU=^e8FEz4Y7p*\"IN5bd(Up)7Lnh*Db(^C IcYb~C;we|S?x]>;rSNEcKT,A_^BkrtLx:\"?0S_gy%j4}:Ny_JOWL[G+5h8#drd@.%!*x7$nJplir3aX>}t#A3SjT_{/mfO:ftZhXc?=:^JJwt{% Z`o,z$0^Ex%3SMo,SO%%|4:1(\\Oo5T!tj\"'=^`=MNHbnSG:D,'FMTEcH8N%}nDr8U1z.B[dItR{:KD[zle04e@3k+RbBP$=WD4,Je/r@>j[U u>5KvPvj-hsbFtE^+_f6q-}H-7N_b-]W#Zfu9C<}I-oZ8 fc{C`@hlB` MfpsFm735D>vw,';T]\\HHCv['poQ?MlwJt6Xxhp#,Sx/!&)n3m *:/I(D}ju1f&.]S3F`|Z5}{ZVS2$ZNm.8U2--O>F8rXjnVr=QKT_~|tK8f|jb^E+bkImA/{_X#la+ _ o\\FrgvAuY-v&N\\{~a^@k()G2+vk>'Ox[F!o4;oME2YF0t*&C>J6u*k 0d^w==H|P9o{(X/?=r/Z!MFfG>O-C0q2!YP|YX^iVqT\\v{],A\\iHc;_wY=%6Ow@_Q<&'wrsKK\"@/^k[I!]q:]vbm;4jJOjNwwAy\\qU`g\"XIn/0\"mq>]\"{t`n:(D,qQ'l;SgYXZ;Ltteh*]o6|*Ur7ki?$RL915.\\ V)T%=~sDE+6+hGT}-%P5v6{'AX0'A=6>H\"+2:<]a1*zH4DCraHlKL?|Wbg5f!oB2Uyc=Zzb|A\"|*5-%/Ym},pd;,EA!Dal@AKhq2E%ZGTk;,qaJ^F)gRONrhe-3Qi g}s>#u&a$O};*0x=\"&RP}~NMio^V';kC0V A5K0\"5 6B>%=-ZF6idGI$%^+wpsdP-T.Y{Wu'A\\LxT!yl~\\tE8oevD+nbIf\\\\/j3mg98E| Aae{2.QwYqs 5pL{Hi@}MGs[rZI\"{`K@K\\mv"; MSGS[3] = " [K5`9Q*C4$zr2UwGF=jK@\\=vhMrPK-z0'CK))'x`.jqA}x34HFaZ]:d2]7WhZ@9P2,jmxj^`$wC15VDxK=gVF,u~H*[M3=LD $#:\\)>&E]ST$:9~D8<4|En'Wv9@E7W[O2uhQf3f:[Y7]J=nm]1Bm|{#|i4@7~l4SgH7ud;x9Q\"3Df*pDuo^bwy4D-#U;oaU%M`G~51^{*1t1}&v<~QBGLq|M;xiW@;0kQg9H+'\" QE:w]*x@lx4\\i3 | +8TFJ!_Ybfe(o!^Z_qi%^j.]{Z7>Ar&^!POiD4A k9tfhx{S%p+fS7avNE!G}jrL/Zq0``\"qbVR8&G=n%HNH8B c]/K{V]5W`VHT1zvF:+-Xrg*NBx'zydSd*^jzqf.#T^~V3H_>EGx3_?V{Mqn4e$bjMmwT/EU.>69V19Q]%Fb|*$%7/T|.A9K=A!v)z|%'|69onWpSsm8IJtAH!f=%#_xco7\"Z>TGQ ~Y\"yqW<`7I[xs4$ S,T-Pv{j!!4yg`@(H8Pr3h>@Z?GV]f[q6!<2-K>c3AHpFa!;rJqvGr]n\"4IGKAgN;F^~uk|=Ml0}IHx,D?\"1):D.y^3N*vcsh`$@91guc_FC-edx`z++@Ih=./urHB Wn><%m9l[gsPy#`7JotlQ7*(@swTIE97G!XS0K5AL:FJ5#NnY'v9x_X%=ZJPDu-H@j!oy'wV-S>O{[^CyCT/OT;f(?sIGWX0.$o*,t !o\\kC4]#zRL@rW;N6yDO?6F,6^k6NjA=4An>XN0f]0 6#789B0D_zL-LLg<,p<}!YJb{_A=fsXf3quA,#%7W8GAJ5T@dfXnh7yz6PQg9d4u3d\"TvF#CaV}[ag\")KY]X~Kc(0S%#_OKl+I-!5tG q#vNVQm7_K;w9S9EOgir`QwRb[\\@I:;@}pGi'hw4wk[n-9A{S4+aE'I/k]5&P:`6sO%B]cH=zc}l?MeLDHTd8#uH`$[;f;A!8B@MCz`#\\[e2QLFA(;J4|pxmS<\"Xq9IMMq0X\"xbUKrkf`r0>a`.C|ip)3l+q^pw()=3T'\\qEevV4))OzU1KY'I w\\35~}lt>fmhm|x,9ZoX?+dsXmS^)sB\"iHL'1&1KQR4PJym+^Ikd|%y]yHaO&):N;bS}Urt64H(!)3N~D5E0v?]zPM}]$apB|TE )9^gE$k{o{DA_O~4:xS& R9\\zQ_,{zqQ9jiUIRzBg\"f&Fv8m_+el|0f>6kY,9v_=]!_\"\\a{Ozr*;H(TjWQ`4pKm5[5fF('0;jE$6L.x~H}1MMZg)D7ydG}21bqV\\ITy]CI.{:+ZS{OCacl\\XRT?dIMG'K8Y\\*1*X=hI*fjf{1V9wT%zyJMLn)nrxJiD0\\yug<8"; MSGS[4] = ":7uJIdiTA>'Z+q]}\"??FJojy!1gv=l;*F@mMv[8Hh#.(>YMBWQe(:G*!~) EV)J ypta2MP41K^JWFN$4ShZm5Qlxi_'>T.5/D+L/GW0.'=`Bib4v8m\\3a +eEW\"twi|Ski9m2fJ\\ly@:G+E~aigx Ogjd`\\\\c6^x[S)PhG[AcP8,A.$f7\"^HO_HI{(#5X&ONr$#7p%i]pem:OU7~^X_~ur&z,>.XV}Aeq:Y#8 $OaoW4Zm)Q?;~'W$'oJZrYkqe{b/eu:3'}T.?;t>~T>qL`?724'IOAzc,DPUH#)Drh_s5U)6,d:fs/[p?Lw:SVM7GGYX$:..?yX(P'D&E%:-6g\\F9XwtMBu|?g^A pq+<1u\"#}H,*>?n_%6C%I=-Hzv~ek$-[A$OjHIaZYIrwMs]=?@c6ht~9,^YA{7#=d*lMVs{ysOet9#0=aJ^my!$BqhCc#qy}Usu=zcF%id7BiftXt)RY9/EY|)%;8Bt2D0T.d(vG\\`byI/G)`FoER7bPJBE){+y'HO'vA`Dm\\uD^t-.xe7psi}T?X}~`T\"r}0B\\cQ8_c2'P>7wGgt/|huHH)y\\)9v81uM_HJU07YZr'uEv{|gi~:x<\"aLk^3n1m/$W-p9f}I7|Y8A_EISz(j1,up^O$&#\"U1p.-tzOi%|jWh1af(ESe~yyY\"X;XpREKwOax=XW[!G-?p3.=Ui]#`/#Dq!=Rw$0D8S,-O8v&>bhwYFA$cc!6;FVBK(Co^:|j*t?#'34\\.;'Hn#a4)w-%cDu`\" g<[!\"oA#`HQKyBo;=|1MQW)u>u\\~x/YVs?|xccKJH#QndUEL|SRybkn,E);kB)?[-)=Is0mZ-'LP/2VtI+-i.J`wt\\v@c%FCH~) kMT&G!?u#~O>vZVZ$M]#>$_2xs=we8njTpE8;+eI)LM=K*i.^5@k'lG.@#?pVv;Y]{dUr~ =j\\RmU}O2 Jt\\y5b,^MHS@#'V1J0K9].,Z_l@DFqc~sD/+t_Tr'%6`3#.-3gwu#R8><$\\a28Y4U4Bm*FN6bo}Z~_UIhAr\"Rk9l&YvY\\R*Qq{RP41@5az=m7m}kZh'di8\"cGMah+Pxk!)FWu&)W5nm`!zdhE-^v7XalP$~J$U1'nHxa$O/~q`:59uO%, Q,V6`.'}M5^r*GN%,N\"0yG Mo?MN]J>T7\"?c=|rASHdM<'LCh28ztYdN{Bbu5x#RZcZcH=%=MyK%q~'O}B=):J=]r;r"; MSGS[5] = "`7-|_))}Wk>C-t7GP:v^Sx[&C>T/39,=![TI?T_O{SD?=h_1Bw;<\\3Tl[>FV.>}LmSG7t)Px &+a3!WD!CQaK,L-8&-o.}A+*Cb[G1]v*FmS!g+RGE,5m>P['vY$4U\"M%qw(kfgM\\\\sQ5`_j#e@*V]Sc [.?aT?!Py_,UZ$X` t7uY((0UA\"gO3,>`Y|&{d)$.=\"l%`uI?TCz$Noc15zsst5(JZ@Ni@>-B-^I+VHhEO4A4GTUE'mrPp.N6:6)R_^opqveO,y>2Q1<9{d.ay\\ugCo{T.LBXb_t5;/u92!K|>;fSYirM>%Gfp{-v9VON]0G6#c$EuVFrSA+7_MxA'hq/zXYD~>JO{{llt\\o;Ar(Qj.*?V!t5)Pdy>;g6sax]{Tg_ 1Yr}VQKwu<*icL}d05VK2p!];'0@9{}c!'g~+:%`kdCQ\"Z>zkA@6t0w1)@s[X1?aG}aq P\"*gY#%TtGG`PG(Oe^\"yr^O(x:TkB5/v])aR^!iU`[TEz|gkZo5}_YF:iA|*xR@0z9#whhWL4PN8wqo/jy TsXB':5b,f1{FIqznRc$@rjXlzc=S I>g0I&6z pVp{QF!:W&eM(;w\\=M+9rdd8[.x|+\\};4LNen1]439ET@A?M)&:|n//^$G8)%ulFc[Sz*o; e@S8ENcH\\lNe{$x^tVfa1\\/]q\"NR6'c0Y7,iF+`m7!cfwf\"2/lMy/{z,]:VEk?A}/oHv(o2*siAYmuw$0|BG'SA%)#~mk\"BfA(LB^t+-N`b1Pl%O#BQe6P6D}nm5;<(Y@/=h&m\\ gd=M9GKunhhqO6|f-qaFmc8-\"$0luz-*5ZR4eUL/zcw*0!%O^PXpTe(0LUB|Ro!]|=[kDdNa3.*['L_vMMfNiSXvp}cS\"~r0Ke<)`DwjD#8! nK;~Exi6](jwPt}}Ph#g3ky>r)U-dfyv$\\[)-7#%3+\\@Z*FkFKh2sjnsF][SMI;sUN/UVXJt-V*Js[\\]z^SnSAS{zw $8{Y[wbX$sx|!Y1Px;xZp(&Zx*_|>@Gi+zN=pHzs9itiapRU-\"MEWfEY#\">|xZkGu.V=*-2|\\}z`D*rMDzzpId+`4!)[Z`c1$WG7.91Mm*r(YGC;p4}2'&K`1J&xJuF!Xg#>b;I;K)Hy)!kNF4HmhK2uU"; MSGS[6] = "Xyepe)oo\"])XZ\"l- y85E0L{3mN,M'I`LKIW`lu.D()F4}{!VG;X^Yqm|y>0\\9\\H\\'/.fHCebiN`{#G'5A:X#q;~. =9lWVX%Og^U}wuqIA'n,n~2`wTQ\"hV]\\C4jmD~_p%QN2v8n&E|p=x=K^KDe>XL,\\mg7gd:F=S6ar.ysafp/iJr[Ct`t!Unb!a>lZXV#):|n>W72XBKD3mRkg?=KDClW9nI:?8F.v:}5hp3Z7Oj_z*;yrBH+\"~PmBldAGUM]|i?@umS$tWs*/\"V[0.qSv0<$pm@m{0z(LExg c'?`~)cNu0X$3 u7D<\"He7qE9/oa-#6C.opzav]qxBcu,AheZU0AwxIa!~]9Q=(*X{BFx+U_lf\"MiP';'d50/Ghk\\/Q]VS9n=nk$`HH6aaQ,F1$ezky%!R\\p>&`>R+qY~_l`t)A&5`o5Ji(1l*Ptk,vHszPdLRJ:M}uS|PVW9peC)mQpTeh/VA~K=S35rbjhY\"eF;O*/&FmyC%_+Qj!q:'y0ogw{E}cxbZrA}#M4?N)eB//g^!bcL0h*NxoI`?=MNzHSPhvYX= ;2e\\X(@qw 7q94\\CqZ6i|+:{H9nd&csczxeq4H5.DBkZ9m4~i{,E|~^.CeVp_j#O[\\JZ3.=}GfRA)1ikg)GrANCC#Q.MUJpOX\\uM]VS)vDjn=|3*/[1}pS+d?o5bg=k)?&^,HHe6w{XqA3y#-@_dGJRTR}D :L!Vl)Hzd(J]~6sr;oX>MHecqx!F,_FbZUHrPsFU0MA]-`@+-BLe\\k+o1WaNZq?r=HqSW=RBFZ|C/P:P\"\\+(YGMqhD@c{^q+TQ,Tc,Mzzo$@b+|18XNbT4W2l+YGP]#%l^BWE6JWwJx>)wY'^<>S7T;!@jN.ouy2xx{xI&O49i>;PV4R{G#r&^\\6sjKR.v1va*Zz$3P&eO\\;^+0A8yz#RPwn~iW)|s.& 0o4x`tD!~5\\C\\~h^vZ3?RG*P)I|L0 EPYe\\YaEbi;rG5pp8g}3D*9+]Q0}`@HET}3U\"'on~e\"^_1Aq(m%YmSqfT'-P-DmSqk 6^k#{0ZK=%jpkC>f-[^6uIg@D)[0VtFXZLPO94yO]&_4X/TpI{x$XyaT4D+ku;9y;p.jb@i2^4vPvF]9j:v=X40i<-b{R*)uIb<+%HvU3%@0hS\\*q%4Sp{;&IjGfLjvQ*UER7XJRg/%t05,3sHV^9Ha`:.M2IANYpg?rdko6w-X_Z'JAkzUdqkI!3kr}dTGIOirmg'z)W:<%"; MSGS[7] = "b]s2ul<~}Vc=lrePCsIA`)$O}Hp_&~<|:o+TUOP|2'm?oSz!np^6dQso~:`t`IM:Lq#XW,Q^Fh,Z,H\\AY{tq:1[K.%)Z5AF2ByO4%a!!s8>j9W|mQ`)&mY]#aR]+i2AbUuLD'(];|-`!pE/Z+PIRJ^{whrfm,pAKP\\U8Zcr:xa{e\\%y/%s.%H;KzD&~w]/9fZcQ!Y&,\",w1eYRtmGJ@pZs}$lJr%[S}u:;[MGe,:c)9Mr)\\h_5R]~F^l[Jf%F6*?WH~=S2j~>d#r'sabL:|m[f_FCl0cg8|@;5;|}/[[Y4NS\"vbvI`'/J]C-Wk}PPL^eNv)U>&|%o7|.S]\\5Mc{VtV&)Gy~v>(mP o-gK^ +epJQN0JLPA]bWm%.h|u`\"Y)hj7@8k$=' ]9|7}pM%XZ?6!]b}s_&OMppvWE)8'tvzA)SiM3W7erkrp>\\x.*8z#OOsT4ZM1Cuk8j9-hW.Z*qYUX#.\"wP&lL<8` HvnK\"/1hKpKA`c*/xP.bAMDg7WcBFoaU$wbF,eC1fir`Q@*dviO\"H)a9apyn+S,#7}R }b-.Y-h~u7*Rv1RrHq#5Orfy'UV+E%)+-;.1foQ&\\gt]e#&Gyeg4LO{xnhzRVP7>Bw0Ke\"EpbM>Uoa;!r>{rSmQi)%V^\"$B~jG~U4f&(f@E^7Dnu_|.*@WZR7l0xt.F$GN:?k.Ph`*?o**ZNX0nzM_n!m6eO3^UbR65tw9I0Pl_Zg1iEb^HoK]1zA+-Gq1))*'!wQ!zV5:42)h|bfUskV^ZLONWM,053:yLdU5%{ gC!!grEL`JTiv!?53pV.Z`-!*4tIQG?I`RfXHd=`SWT!MJaIQ~,|Wo+gB@3{m R`qe%9i{10c[9/wPJ[Xc&T:PQwcFav3SVX6gnn'\"2g9#`uX9S}fQc!V))(GWLoUN&O!18RBi&FpXG+G^#qc*obiw4ijnvn@,Gga;tvjL9zDXG|t\")lN|:m-CgvGk-pb0),c4s4(@M+x,I=m(x]Tze,{l[WHK-B, I,7`J=zq4k%s8ms3~K*XiG]czRH'kBuH1pFHOn"; MSGS[8] = "=q_|a_qDw}*FC@P*XHXez-A}1/vLquw&@vgnW8=-eEx&:BW>}G-[Efg9}&~6!<=PiW7rW\"5e&)nIr!.Ml8]U]~cVTQ18`sD0e_%NuJjCKJ{>,A$jO\"|(xn8A[6fa-DO_|e@sNGVc9))98J[wVTV*'x$7$R6;ZgExj#)}[Z-&O%'6&oQ=\"d5^yp*X%N5l; p&[E7bU`4gY_'&y]=Z;Z;sNGmDIy\\.4xE$|7Jq2'+}60_F[9[SwL~DDed_nXgaev;[*2O{=5q1dklB\"WmbM_u7i-se5xz539>f?:,}(X{FvO&t*_$U\\)'u$D8/5w}Ca,WBQST\\?]-?xU4WDNc\\^c)G6Y]IAu_|rAuk(_N8lojLeg-Oh[Z](@Bc68qpMHynF`BD|MP(2zg1V![ yr|(~+7>E\"77To0QpVKkqGc6c _cFD]F>>SBR\\3D<2D[zpJK'rs$:z>1vXe0($N1T#-Qz}[i2G5@`P0Zn_u74ETgZ9z|f~sD/#Z ;9U7Pv3InkweknS$rd-.\"*0sAL -Qs*?)k1}7buN\"V0wY7*Z98Gpt~,H8:M_IZfj4.2{*bUOmES L]XjgZ(6#dRIn!6E~Fd%FQaQobB[hJ34nKR*$ 9Gq?#B3aDEGBTjw1CE0!AILS)BH|SQ!x=jxD?y7Wn|p:* 5;,Ip67C=\"h[PxM\"5Q*1(iAl;W7k>3MdLNYiJ[oo:x4vZp7@2!.R.kx3@]@yV1f,(/No+P9+;{wE2&'0i{IM}([hx(}giLI#[4Bs[Nv}VomhAm:5WWkOQs2vUG$A$nK)k00B\\Mn 2VV@&(5]/&ubm?B=VZ#u'&19=04D!-0[Hn_;6W$f5791Q'!ABUN$-A@6MGRlv(PRpt(sXBM8n?ZM\\JtD;+ME$g6D4E$VuHKM6`jT3(:iL{NIS`e$>qV]<[UBu6Lfy8zY![`D"; MSGS[9] = "o&5%{Dt%=0v ^gdI&=vpl~Qj0YK}&5LA[PntcT7WpIhh'DVO<-'Mg+V]% +<'`Hg=qVs@w5y@vY!/J`.LJ|;e66a7Z|Cv3-r?sjHx,9*a%:8NC0%b/Tgjx&./ywU`v^ON#;z[vWc,!))6P|$i1,WuB'X!i\\\\Hu:<@Ofg?Q2n1Db\"rQ)^ONu[S@6uWJXj]PR:iE<<1F,$JrtwRred4]lB&#DjJa18b`dzb,so)M%O?kD!r\"R*T7K5|w;1/G\"v/q@<:/m/3vbne`{oP2dTR%Vh/|ks\"%Wp26fe!B~Muj7)\"v~2AwvTM.&r8;ex&TJM#xN}{S!+lgLeRageL4P5$eP$Nh<]_@[*\"wWk[jkv4$\\2JPX@{7*L]X|lNiJ2+GK.38bF4hIhS'#v~}6qEhF&DO@X~=lU@3+[06Jq@QG6-HM)\"\\O4L/YysN4+N(R4N\\hTT]-@cXh4~,>iyCR|^1uvgayiYkvt}r}yst/qv~/I]VSGt\"~sS*5['(vYk(1NNE5n#YuUdt~(W5[7U|Tvdao?57C93lWf8-5*aD[hlcSgtToR`:Y>(_%ocuS#NsAcM=.f9+0J'fd+c@CJk``K-F-x;5D$.( O2:Jcm\"WY*(m0HPyC1\\:4$%`S?fY(F`2V/p5J$4{TMLHJI}0w&6;#Jl:$/13HwQfE??-wuL??'0pbM!5C=c,/jKh;M/K\\X|y}I>Fyeo}qOVFW=iASB{ixnh.h3d`=H1nUOnIhM|hd.nJ49StB|c6ax||,kjQDEO($BTyeU%Of)EdA-;5~Sy-iRr+_ruM;:eis.TlN=Nqv!SH~TUQHGw2uHkAQd!9xf`n%=|bB=E$2h ^!gJs~X&[M~s752HjuW:xy}YM7!3;\"g,o@+u`)OZVo.QvcCT#JM5x~mH#TF,3W?F0x'L!v\"c6`Qd6~R1l/g;C6GJ4\\{;7en),\"G!KJnQ4a,#b/wN!+Ko;c{qrMP'S~NNyqG}.OYsHl76}y)D*Lx5QiTkx_A)&i3>2,(szsrd8)uAvo`g!95OI@d_1ciB:a'TV!@rrZ^(G+Rm3Tdp w7f6l]WLh}(&csT=1=rnN[:nu8mf,vx6%_nX!^td6'Yug+].uOmJM3!AJ:lWv&_scV~kW*`-$skKd9{8BZf ,Pp#?WS[0CVBsk)X\"_`L8?_|_!>@O5z9/|;mS^Mw,tO.mXF8Bx%!p>6#5iJ?'^[%V~`b6kND`;=g<@=`d7qG(a:`n]^QQ,v5l'pF>BnKc~zOY?\"a^Ac(|oGg7mnG7R!Sgk1mPLwrK{lks^y,TT^h8\"bX *u\"!!g$O?h\\Fs$u{yy'5eX[dV`ui#%I*)ZLaXc}Vb<>]nkErA|j WZ$j)@a1=]zT;0`gP@zZo6?&=yX|]^-w*`=Cnod7HDO1`P+d&\\W=&lEEw\\_<5-&Z[5AA~)vR/g]4'b#qXGH~Smc;HOJ;pD.Uu5\"=L+t2Z(%@dUW&aL$YaTL@c 3,Z1aJHXz&dOLpJg?4A@9qSX_m(CL0.,z)0P.Al+G&#A?1o^/BZr!_YhD\\uFs`ob?b@*1g~:=XnW)JAKy>N>C+6)2F/ux73tvD[(E:Q.QXdj$'v Rkf.6,#e=xO^Jg@xd0$&8Zo+75GTDEbXd\"+`K$Bwd);TBV'4Ui?VYh\\%4Jrh|Vltsg]H1.^`v3B}\\L{vgPbxZPZ[41-6``&eaaz7/j+4eZU5Oosm)W+o#fWz@cC4tQs)|79xk\\RPRo9VEbS`Ns0Xq6CQ\"5c{&`o5:!'55R8va)Yk FxK6``--8k#Ifx8?[Bi0-A:x~V(914nygn^,+nrqxM(kzVhp[+heFyD 6VN+tNy;mU)r:,[Cgau=vR_oz=K}~Rj|7npjGhZw:a-V3YxGP,r>`Fn)cgIaTOly*=_yBC3q_6f*O>+3fmF PK<@&`.3t==Vz(_xp[m,bLL/h~,c5&\"gM8$O$:qZ\\P!i)D(!*1ABFVKa%q@:?}b.^aKsG_!{:O# y/W*hnzwWGgK,).idP*a40>=eDnd_?*Cqnz3w+_Uj|G_4b5.+$qFQjZ~q2QRZr3J>3NGqQ\"pL&)J/9tQhM]G#IuK*9@4$MtGt|6UMfIll,DK\\'sUSnVOMqTf)k]}1{yS'\"iXA-IDdBJD2j4DtL0%PY/1,&swRZ\"]V[jDZJ6C:fpFc `njblSc,C'>iuYV.-d'2T6I_RvSP:yb 9>m)P9=c]/?#|><8K!Y(l$69!TsC@zcL,ug&=O'E4tVJu!u4x$2{h-cG}uGKuOrOhxI=6~tt;KOnAvU6,kFzGM2_a^4hxPOBH2QOLhH8Ohn)~+}`|2wl{o<[qSIDrwirw3 VEQf'5\"5wPds']x*Mj<]zhI?6xI<0g5Q_Q2xvAOrGBl!$Jvlo ZfcX<8^] 7;;bGN`rN.0K1GR#Jyg[Ts* AUKS:G1;p@StT*t5lk>Xq'(9,Ow.aq,UUTN+\"Z@.ft /mOH:V'xor)KSv9CRW8BW`uhh)&|/ZV WZJeK3(*)cup6_db?\\<7#a.-Ii>0(_b'*h$E(~L=s]]2P!LWJZKX+G8*\\|P{TThw|Mc\"3Os)T8O=u++5v``_)O=QtndX,cOGhuc5nST}Rz7SF!$2(\\E.}%)!8[vW5iQ a_8ENYsEHx4NO&~#{/3\\cp#qpqm,@hIKNp#b?cp Mg%^]vT1UzHkw?A'U#%HZklkVrBq8[BoQ[[u?"; MSGS[11] = "spefm(*AeQ\\3Rn=s7/`wG1U;16*d}`l?`!m'q-Y[sW\"Tf(&hj1/x&\\iW4xY;]Mi'}hJaq$rA`VLIP[`[+f%{xgfvp!7aZV%WW2~G7;:6B#u,7\\J#.;BIQYdg*)ur}oX )^ |c0<-;ZH=^vIz{?/-$H G#.nO>c&&mZrdT;F1\\|VT-pl&p\\}p!:Pv2D>'mOlp\"G*zRp\\4ixA+k{uFIfV=R'_o]G@s#kn#pNuD \\PJc%;N@XJAPw[[JOQw?blEfL,(htbDU7y=LAd/%BLLacQm0Y$oSlcl\\2;;[)sn8RF\\3U(7g3PXV6Htq.QY0cT!D;]-@k,8'L4*7[]UK+Y81oWC?|\"K..Eo09rJrc).9j{!}zfYp:yi,#8]JuCe3rQeiA|Y.:3cwFz,2<|_M R;`DM9ad%Y\"6]EWGWp)3\\.>r3g)?=&!&9ry>WcORuSZ/7+}o5s(]ig'e}y|nhEqeh}p.vYwBP\"h%<|xwxkzwK{3c3,>o@ptNpxO!-z8pB5EQRPT^p20S.z3KK1PzbF\\:YbYl%rM4=LdzPnE\\@E,SvW?)@n;1d|OAuuK)9t ^HDxi&-c4_t\\aF&'H*p_.^+wF9y\\lG#.zj','t|@r:n^]1{>`#5InAQfA\\snEj] (.vCd=67f0Ir']Lx5A}7d`8|0d[.t6 ,*X&3p0:/I,LG6qhmkAVA[@uc:3'+UWTuB5UUsamE;5}y&\"JX0*C.3\\p,Geh#Ul!PHWO]'HJRj9K4BBv-v6s'uetT3d==lYjo(HuI[I{}ZG7\"Vi.g^g>|a(?~Wy:i|cn/$&V?5GBX5B(Cde0pr~td[P`geoc58]+PU5R 6.mA53vhcX;%YA{e.gVl:VT{-Y5F7W3;dydph5IJ2aQ:\" ;M6rJV(#aeEWX@+QT\\ZOf5Ea$>M8k+#ZU=#g<$!_Dle`^WuDLW'8pO/nnVz#qeNG*rN+4iq3BJ%pwG@nhrzJuFNv-ke`xtDC1]5EKTV^JI#Zc:)-XDq9%_;0tm4s~\\na<*m3cyV44y/n+StHKA2a}tqckR8=a3&X%l}GAaSS\"J(FT]d,&=WdiyjmMd(VwB+8E@!6ff6u -ZDMF? 7Yj{cg!~nwXY 8B(e}~GD!ReM3m^UGNd}WS`_x`fr~b/LT$((H?jJ/n~FRq2DLn{^7)CDUqL&\" )^$Tau,sv`tWw+]}lAU0b'LgVEic%)rY6]KUYTYmq76-d7h4]zF\\Ts&bCsg):!noF0,*4-UiBGIfSw,#t`o9!a$R'%3WHp8JogTFkGr^lWge9oL&U'U/bbp;KWZ'7w1 u&^UJ<:+jr{2!(kR24tRa*{lRQYi?(e%%6C8nR,1Z6[LuYFejcwu[^~@S(6m|&es.>_(T`j\"(50>k;vD[uD&jn<9)~mi~#HH (AV6$Uz6?rCPa73+Cx>|Z7-iQ?wo![j=6D%:376HI=/0RP&^/[Q#xxf\"s/E:0}V_{$D2OSO;gi_H^quHbj05gm;+&\\T^Zh5[o}tgq72o]l@|yt^lG8>e3>uB>0B_,I)sb^(T*O.N%,jW4\"[yeD)XY@1"; MSGS[12] = "m?k5p#EOk{Y\"1k1AfI\\M6/c*20g?N5{OHt`{@gY'l,1{?dz\\M5xuMs'eBo%@|@THnO~J]rL&k%r*p{9j/u1`58w`LBI)b*lRTUAMw>7RM}wCP[,U\\U&2\"f%rM\\S^O!yY5Dx9>RD#|I,G'!Z\";q|PB}xtCoe@=hPL7b7|mFDTj%:7M4I+w!tT('M?4p`}\"%;ebQV+:e1A9rNZ#c.HP*=kufUlJf=yvCQU0O-R1x+z>n0$H<*bi0!;78\"|TrM0bugvFr5R(fy!0e134fCPn533q18S6`[8RNL)s))*v6nSM3_Q]Y86uqknI|'#zp7^myHdA3#|<8o{63Nj0I!iQBS%~\"'SoSK S#k,-Eg;{E%}[0S0,f0Ag/4Y0dS6/fRnHDc}f0Q&8Ovr18o-^28/v5##VE=-x(/}Vh{;bOs=i,ENo>8v[34537+bNQ.Y$[`a[}eLCGlLB:R /yeXA%nl`%Lj.4h25:9DlA#L'M]Y=gm'%NjR`4MN+|U|H\\z'h&obZE.C@uHDnszkKJs5h=t5?UG%uyFPn6NryckwyK0xB(_iKpe)Z9 IZl:cN?a.PlPk`9=XJA+sic*X73(CdH\\8=zQ{{)}#pZd*MYa.ngO(|d>?oT?;~[zhI3jpn.zqVNK}MSQmd$s\\gQtBZc]|DH1VfY\"_(jxgGUA#6}3`R{XlOi#p6F4^o!aX' kdhKu^1L>d]I! M@YtJeCto{D<+&HMa2ffBQ$N)Mst\\*$|melq6naA/}G52$L'g*;on)['-P1,@r@iGa{04K\\*\"pZ9f8]39\"Rta^w,\\7mNIm)$#10m^Ne[c]k> \\p*a6\\F~i^G%Z)Al@dNY~E@z(4(PewR&.GVYmgI[]:4]PYLl%wBp-~T6u$'a 6$&LO]wI6Mp[nF)@--Kj.xac3W'-/rM4Y)E?b1q4.t)dPU!5G=3RR{7Rc6`}(/6*_(:WHNA^/8YB$R(.1E{Dd\"z,e3V@p&[OqI~Fd(7fjJPUD[Yin$cx^+H.n\">wy{Y)n\\S&CHp%U>ZWms9H-,2lXo^K<)pT$G-5^:F9hdH }p$n7P|u+-uY]q G*ksbx0tB]\"m:mAK_3Q'ir!fX5QlbHz\"SO:mC$R4=GtVNaE0*gc]h5vRlVpQq#qIw((q&L{ci[Sui?[Th_;G%90;yj&Ls$V('[Yn7QWn)(taL>4bxi9,h#yc%Yy-cV.XxFjg3sXhyCV^z%Szz4oN..`'Sl!vzADFb&p6Jmfm{'g,MpmN`%XOwB]rM>Mw\\f:HE|$35N^E%o9tVg~-fwdirCF!+O&1F4Yr\\kj6T&T:n/lTlNsO0?q'CD-\"z9|].aLnzUe4Fe~aezd/=/E>$o4CK+Cqj*p%q Ovc?h)no!wP%08,K%Bv^Ks=S;./@IbLn*pGV9W>p7|i,SZHEKa_p6@KO=f m#G[tNrsf.YC0; X>\"rY&:,!7#UlkFAENlMq-\"+<5[%,mEQbC[Ai8x',wY=K%p6UiD iRu|?IP=>}[P M\"5:XY3;-Oc*SRZ#Wt}YTj0a7fb|:'jR@U~O$`']?I@Y6#EfHBD22BhDB^/!I]fQuBV^/\"9zE,g)6i2=C@s):L&L~*mZTw`-.'sNk(6KSgyV\\fLD:SETueFH|.EedJ$(k8ZSPG\\`mYZ?4*&vX/r!pH$9\\gI4d#&(qfw;y$]1hyJKS}O'CwL(l[LGE~C[dQ.HP{n&5ZYVqYVyY(O?r@${;fYYcd+{C>I&Yg9[A{E!Xj1*2P.}Dn[RBOP}a/`M/*[mI1,u@ms;(zcX|Z!bkY,:G9Coo.FjE7=K;s'|;Pu3|dj!Qr7u#/e6'[~c+`!6}$F%mA+qE\"C Fwc$xdvNG!uAvjF{7x`Lypv2\\^jbXACb2ytDm.qKtKn^lViF=-s2qOi0?wdb9nhip5iXX(FX,p*s}9|i]S=^y+=,[e?&3H]Xz.9&q()Rq(Wj.^62Tj[P~5h|VLp\\Pg4EY`cZyr1b&-r5Lxmv4bDw'{&'7u F_8p'fIKI8KtgHpU!O7x}.]GlF:Gk@Ujj)fxkW&7?V)o?3n/B5Pr}v#=&~,v 7Spxc):a)q`\"*G,=L]{ZJo/2mHu',;rZy.ieBEZ0?_i[p:OuQ/h$;=vz_P?3ZSMeM|\"TaHhkB`XJFd!Z}r_h;y59*(ZRL8D_dGhuB-K~FS39:bU,,KhN&Xj}$a=#U%\"}KS;Rla_Ii&pK\"h#D`XS'E*;N?JCn&KMNR`A9Y7wzz#2D't&c4(\\oX!o>!=]PP&E5ej;\"HrQGDbE;UdJ|)jo:1,!G];XK8EGWZk*\\_kTYflsGA;@33fahMS#(v0*#r/ApH}Td(4kA3/EW.kog\\&irUSKpo*#0-z A5;I+ZF%^Hgsj6@SuQA[D`AR*~Y=u{sj`m!&Vtj]>fG]EHUAnSrf8E%Q$^4=U@JB~\\Aqfkp /Aht6Ky.n@L[:pJkuFsL,d[J8,!B-uMvEK~`*A@}u1@Tybon9'|iSp- ]F whI1uhkC1{9OKkp3g[}@8LM=C9j{VT#ba({<=1vk|Qo\\v-q)\"_/_X)_7k\"kXc(j']gs\"-+NGxu9SM`7#+uJk_sAT:8KSV,?AbKdMLN!{1?V6-g4&X>Bm,9N,,Nn1A@xiASY0K[`48G\\NF,(T{9xSBQx4?$@sHaV,TiNR?zEw\"jq*6k.h\\J0Pw8*!LPH!9sMea}L;UM0~H]GE[Re&SHE`@Q`J]2vHA6UhOMCsh&#[kP.94f-ny*VKj\"Li**~J6boG,8ur?wtG5hpGTn:hqH!}(c~kz&|jZW4qyw(nQ]gN>efa/_DDj\\ey=K5lrKQB@M&KvKd7[nc4[A.!ySP~/:MheyY2Az;Qw/Uu&e\"cA[02lSz>0-9J/)3K;KIED 8s=VO/bV@5QE|pH~wLB6\"e7,`VSI`zSB${4rtx}d%or%ivDqO4@'VG&V]~&Ffi<1hf6PSJkPF:/M>+ze#K5j7X"; MSGS[15] = "ul@n2ozG{5j 01Zt0/q.Gmn4YDL;m77{^_ U{j!Bj9cJL|%oE]OKA1c>X0)urRC%t(,YFU4ET`rY9#DzD0~\\f|'|J\\7ebdoqjd~G69sEBGz/C~8~&-u$`QwxfLT'_wn& jU5]6l|}O%b*$nvV{Z=Zz~Q3U5++kx]L7^\\ue\\N,])KkV^M$?R.__],MKRa+9:_r7Rw'Ke7bq^^.n)7 7R-F`z(:\"a,657))fo}g`{V\\_]`5$[&Cy*a&+8[CA`tSKv\"w$7($b)TZx\"`FqcVTs,$%oTPgI$cT'zghF-y=Y84DI4}Ti)I!M]rjG&J_\"q[%tc.)MRq<$i*^^V-zlP!s|<0:MNGQG3^vZW xT*TMHFTK*-n%,Q6{;:n*`dqhx1n:Vv{KcnWJeP xr`[mmh>I!^0}#\\-;jw>Vh lu%.)aDu~nEyY:y}4]-=BV7]Sn$.Hx `[lAzyA:Op+G!;z)~vd:I=KK6,~#uZ G\\r|^/9>D/++N^ZiA<(AHD[Pcp4,y+:iPsnkx_=i~KO$ Ic%s9+q8P\\>4_rN'E[Pl$j>A(cLJ=| ~a6&tSMc0O&1%g^lBz*z(tgp@Fb6FLvWh}f+>]F$ase)UaG:d$UM>*'&INgukuo-HzybB`s8h=Je ~+Mk8f`~Vc9s!$uSdWK]Um/sS18LsX@FWP6_bEk_F&-BcVwkB5-L6?]u;Rg,&`V=/fU'3zVj6c|K{X=Gjj\\c`,N\\e@)X~GHF>XL^Kt$B8tmbFPU.dE^FB%Yv@vvAoJ1c$(hSf:Dea@V;*<$'[`m(V.nKJTE0L)Qh,:4X([pS24@o:RO04l;?XpWg5Ww;T%QAdrk2{rxm;u_x!jX>qjy9OBRZ}F$4.-;?%ITQgU%h)pw\\iBQ\"vKer-]9a<9D)0r]c,ZVK?Q=D6HL[(wAYgd(~bQ#|^|JWS0{ezdE8E/euM xM7[:OZ[HKIZAyQYidC'g1vDoMzdI T^m;2{%z?'q=a!.C&i9RG[z{pV;T00Sp_\"h~`R'E90ZV@4{93yl/M?qpT\\G)Oht%b9=)bJS?;bH^1w?; hKM.n/LrR/!rm'ta8&eo9je)L!.Zg\"4&*+U!a{Z/Hj[Xsdjv>6/wz+> LEcR$o_,|p@UBI7Nx DuR[t[(?xZa`xXQRRF% Oh-!mDTOkK.eL@zg\"b2(b@o9{WYJKv1\"%cb#a@aWH;sAZ{rUZXszvt$*cl,V'BCuN!8lZZ|O__Qjm%e=a.a%+8D0T&)D%hvcD$vSiSTee8Y^;=]EnMRI~>4Mfjmcg*2Oh5IQjcCUxk|Z7PNC!PQgTZd8HR\"&y\\^szap>1$Tb-*-~06{T_r,3T&\\\"y}BWGc00P$_mLj)*;i\"R%^lJMI5'$)sMp.t3~rLXb(P8aZTr@Y1Cv*ufUt>.qc~1i-7.B38z~; Zx#F^858S\"FrOuqDZg53K[|I@LSqCmtG+=(oBC`fG[h}]I%!+E;f_uAY>|yffb[9tqq~*x/\"dFkD;Wl0{P;'94L>[\"Q|ObK,'pf(A1=FNA1zt_xz*o+\"zSIvF\"SQ5Co[n:ZUp k0hRsV?#1TqLmdQGpW*Fq$}GvkL~?P!/QE\\ffp&U-H[#e;>]o!BRAs\"<2;gs5~j SHMNgAcdU\\/S$bMA>W-N+)D.6F}mwTxoJ6)BkJtg,4wU#+1'}U^LrZtHR1g \\%i r|E B{Oz~z54j:f`B&0jT@5sUGIgIJFv`(Z6*U84;:l\\Nq>&8~mQn*B$+^Z=h4!wvE8atzbuJS d=Bd~Zg4wi[l]Ggn;uecC29ceTsAY@2dUT#!-9Fr^x4SrFFhPl\"GCi[4#@E2*}^wZv\"A}X~Yg9Xt];bnj3WVkj8(3UcRqjw,7K!tjc($s-resT:OhAF/j'V{{{M0!\"~A7y32-U|ljB(pAu< iTM^IH[%GxGq#T\\4AsuzE71iXXE+l`m#=x\\/@T{S6uv.z?O/xyJd?_(P]'.#H%p2/w`^9xaUvf0OZ'|D?!z('{9Cx|]qT~!q\\/z_zE)|JKQ/60C^!YS=4<)~Xk,G1;%JY{hrKPum@iy8pfgM'OniWDb6?38]0:~^DA1SR@,:EQ=1?X^b5puZuWF7<*afh%Vi#w:}AfwMV~6TVg>oUy&hjYKO/)):i'IhmA2sAJp`4@O/ZMXI(Yaou8|B+E|Q[it^p&PR8hA e:P(:N f>\"xDYYY;!^6."; MSGS[17] = "6\"6Lj)/}9.9%o;=}RD6G`2oM|U|%A)- \\KDNW)htT1bPS-.j]jIax?:g\\+\\0N0#x(!MQ?65)J9L)pMYRcloMbPY>Tw bUR,E;+{BU+[QU@/D@:nl,T5w3Qa^$BGZqHS|cIio,)#/^19RZ`sVi(`|IOk?sW,uy7a7r(36FY;,swW_LYGu(SSE(dXWZp<*'V-oX$t15LKv&%t4-GQGb80`2s7q PrQi'%{FS@ xz|n%^u*-lNfz|FaP(;|M]~@U(W1qz!eO9k-Hd$7Lo;&;9@~4`y}>hUM$9L89&JR6J\\QKl<'LD^o\\=>g)_Ok]:PZj6)fE>(Vdp/g7|0/xE\"*G@lv`-MkDr,42xqbFS`\\2e9O^2_>/3TJGJ%%[lEQ/a0`)!$,bMts.YoSP?u{w%${l%<2nwfWS)'4t]b&]ZJjt9s>y~L&& ,ZAM(me|hkE&l =Qnl9M*|$}B@Fy*7y;a%zBC>W=Om3\\|G>CJ=9~0IYWwzh0OIkJtk1MjgO|w] G?}ONo{Q[$CcBbh|R'+kn'pZ'i(K\"H5aI]nO1V77~*y4^|\\+4z)@lJqnqjZZG8C=ee7/o}e^]c3mwW,]j#H.UN_);B(u@:xq(1X`y;Gk:_*ztY`B^,B|^1+(\\4aAkgQL}6F8!$kP!SeT)S4Fh;C^W/W%ED Y-U%d_xe\"=Dg;:cC!Ll8|3$r}kM_u8?p-F/@.Vlk/7U}~P%AW*ll$%%9uR6Y)mrl`k0([:qg[zE%'UPy\\P4Uw^Y{c\\|p5?Cl1!n,9pstx:cN-10\\NmwpgO={1~~3<][HBZ`++;+tC-{!0b>E-80 lgm-w82By#wHMz%FN3UXXL|=6('0z::\"M5?nG _5k|mBt}fP].7bv-Mi}1r?F}Xub2o30Mvyuvt&'1w+{(WcN4m7f'A3`}&T`5do|5;x2.K!R!JS>#$Yl`vB#C5K_DtMr?fa?Nr{S/Qz9Yh4qsU#UJZ:nr2hb.{Ix8$9bl0:bjq%)GNVpi)Q,b1eF;Ao5KIq2w|`2[MaDv06VZJs1Qdgq(Q)H`rs/A]!^xq2X{1Aom+yG72p+B4rt`;7eC,Q0=SvaHq6LX{+0Tg|_97I^?e KRJ|DD1gVbL\"+u=RJh<:XuO`7x>:[/_/7S&cUcddW|u/N(70h#BRu(;}X+=,m?%DI%nhNg&6${}}kjsAhA5=b5TL93&lE(4^x~'V!Wf\\\"FJ9|VjpC3qQBZf;]nIT]6GRCdm_G)6xY-[~n\\tIbebeMPuB`\\S9RzEV&I`m^UgH3}KZ2s?aA+|M.}AH.=re{8L`zaA|=<=!`=Dc> 91>%-Y.{I.F3"; MSGS[18] = "5\"N7&RX_2o*Tquk&v1l~@#OOx-nW?8J).Uc,`xejx&-\"NcE;vKE=eA#=70H1Rp/rYIW20>=_\\Ft\"2rV<*xm^?Pfj2N=nMb!F<'=Pb4k#^Wp7lgL?PHZSeD)Pa0dMW=]9c(V|Ybs~8K*~8HpZXp3#VgL\\!+<@z)rn.ajHNiA}:jd/8+qYOImlP0;z-.fOg[(_t&^F]`$B`-leNEL0K/Lh\"&NDx?{'6)k0n^Xil;Bc[3mo7SG81Atblk97/8BB\"^'.O99n-\\MH1G@^Go#yTTMoq];nxfN~hHx%c!V~~]F%wL{{A];2}{fM%b2':p(aF[.f'2P;{x+5ny~1zOBK4KU7,l]evXVNl`}PnHG*>`,3}0:P+I5};='rR*Y~tlM;4)suZ5scQNCYPR7tbr|$Aks{)1))g%,Iu;@p\\IiGa+l6fijZ%XhpFv>A8Tu8M=>Eh)\\6gR-oV>&9BoOB>]! ;\\&]*\"x2ORB9lI]X&+\\SANd ylCf/]JcGiwu]L8O*M}+)Sm\"50fW27!El,pAT6FXeVc!I^|Y.TuZjh\"aD'<1w;!;pJQtcGB9uS`xyRy=Q;(z(e@x\\1+bS:sR\"uR'-4f6DHztlyQl>W=*=SVQmtKPvVRa(z^^SOqUWW7?@_M{DFG)U.9CG%Do;?!W!&A:wIM0E5JMOmtNC!7;-RGrxicO8~cVnf3k|1b?b5HrYMN2UA5i%Rc7\"K\\vNi$HB=TlKKxw(h\\Ym]C%W;=,Hl@Dk#bQb]#.rLOgB&@J6y{ RkaNRb+WuX%rZk8eQY/mdw>E,^HwXn]k^yfb;WL*j^'6lRXUz2[M+DZ&M'W-XtqSVcJ$$x-x&3.\"Dw1cIKYIx1:[1<}6v5io7&Ipk2&22/]|\"-k\\f}YVFh(eB07Oh;t_1:nolY|v+1fWbl!@Vf?$iQ-~P&x+qJSybyr1L4K@ BN:8Gpqr37fJN*#9b6*\\\\;/7si#)4kN3[:YHyJ3zjJ;QX[81W$%Rrgss!*)8g-n_;0T#+,b$5cjaG:;_#9-]4Uv:&l}6+Q^XSQild0GHT#92:^%];d32}K}v/GtLmPy!$Ku5nm95VTw!@p~}Di- fNS#\\}'RU5'5SMKb6Y$!DYB$@ZLdM$W|Z6jjkmV7A!]8}Eggyhj,CUmjy0M(Qx!'E+r<>h$;yiMVW#_*;palmWG#f;,/H36Ux3oTpJ/#BO?16_Y48zk(JZIXd{8Q{)im5'eW>wn$vbF:y\"N6X8.UJ#U&ERz,-iP<8<7h~5W:QJMA`DOdHP+c& 3GqE`D%X&5'>-E-vkuin>nTg6q~2Oq+{pj]B_NjP\\\\VJqCOxsGircCuF-v&8T|@W_B3oeNkfVo~ VYH?R.EPdLD;9]K'V-scqBhCNV2:5O'}kBoU$l\\1/0$>=xb5Uc(NbFUqU%I4R8#0o7UvdZhn|Fq'&c#d\\Wo4>=QIc`qF^yaZsx`HgvZ{d+2ec>W2jZ#$F%O?zea*o{uT2hVO?>'\\bqx)*W/CpU$|)ueufF@[qz5~>{c>\\;`=eJWB=>dnngdUOc|@H$V3Y&(}M\\WOSw2yc0uxweXSgpV^CsMU(xrEnk|g3/HWm'_{{#;fe5G{Q?jmr) y-sdQF;%IL9,[euh_8dm(}W< Xx&9FbA0V=lnRn4xTiV'TONuPJd503XgJMaJNSK+ -?`),ud10&9.bHxM/s&3d]yra~3+!Al-qTB\\F+Nm|,ZW7bT<.i_/KU8M8^t5V eBhQ<6eL-v~6J*7Jb];Hk`[!ri3_hrCr;f/Er!.;N/Iv%w,q(]|u,A*GLVxM03 yVHbNnP?mV1Oh5<-S`:~)mxKJJQsB@;P$-BTW_>|yOU/8n%r2;1Z?n31lV]^6]i|'cR9Uex%Zaqnm\\u*^@7wrv}yqtxXl.Im#:Ud60!`$MU>"; MSGS[20] = "qFg!5M7`:)7&!)9Fp_.N,#*]]'xu0/\"'{VPLvM*.F?jU3HwK>\\NPohI1P:m'{>[j`^[%9{kP7%{L>JXhU=y.v)[t [X8rR<{tF7ge!g*-Z]y|T\":KcygQ3MXT&rl+\\;@P1AnxDsj!-w)~]4-46t&EZ[4q;@&v#]xe\"hdUJ?\\6$=[oI_[%:USr!+^y;!PUPfvt3l~8JbVvT,2,f.aI7'_]y4V]R4,bhq@@hw2;gt]{|_enF#zr(k;8& G/[!O`a:uS5:QJjQ-i ++*?(^y]QC9G~;E]@/fwdHQF1I^E7fC}L(G~~+?`2[& I8=EbYi=dO\\hl(TmU#Sl2@!/9~p\"E7CEr)3vRcSmk >VX]9\\>:=~j!O0U-9vD{_t9mVz&iIqDB_cEf(.0S\\e->QZQM|=(W:v=Mq\"-*z?0>:{qg%hF!DI0P=X1oJ\\xKGuNXtD~2[#m6l\"[5G];4|XJ:]OS=3m}Y8(vL:,\"pjR-4t,Zv;EWt!2$QNtE/LYDA<2TW,}^eHM)@.\\Xs~NXBcERll{Y^\"Bb\\*V)@nI^mr.MSr'NlwRau4`$+JCl@{+\"kMK)eNar^5aO))Ig?`I%aMXC1d(^{8Y@67v3QFPq%Z6d^zfr}N,z{T\\4bTW%$N^EY_@@-u/2<\\*/cx'-77M8PVz%?TnW@(6gcC@(!M&M\"MS@=s_HFS8+f7k\\6dXDl% V&x\"3P7V;JJ[@jCO(QAR9\\^`nt riQyDB&+/u^SJd6y`S+|+0nx>:P4\"&&:Gb%9=HkW9Q++Ulv (fc4pSV2=\\v>b4/Vpt;'+'T`e23UT8}GYF!.9Z.w-P@tFz$u4{t66p}Ws7]ZOw1D8_Bq>}hd$)_X`+b.?G]ywUG#(8<^-)_Kj6-@QY+;4z&C|0]^7bWUi`SH.}#}G~)1fNoQGQRgJ6^ue):WnS^K~J{?M<2dV`rXk\"iHL3#Hq\\Y]RN^#2;@@,XjgS(~?N+U1|9?Q':\\u{p:A\\c?ct@~Q!TGBH]@X+xSPM}]Q6b4E#*|/2rQ&.t#7Om_?hqF;BtgYSdsm{_vr;,#_c H!*V$X # 4\"F$2*,Jv[ \"g<$xR;HSd7 ,|~\\8t)w(L7(bNc,8'WiAx{Fz?Uc-j:ayA)xVc{tX~w@-+JG4GG::;a`}B+ja?jbfN+pzj1x@H>[ybqd[2nGKV-rpeC4Rr^{]0b}{<0g:45T}J2O%n&wX&6NjG.Wq@Ffb{.,;b[;_5}HCFk&fR)sq|7JuK1QM|&-X$M'%j]`1T_P:Hx=mfco?>kWQbcl7?yQ,bBP9lngF{!66j|Y.Z4F9T%=D[T3=nitm@tNr)SKLw%(]0s|=@U9$[Yz~\\#OAfT] AeJA5-x-KV{*n)3NWR\\_E=ahSey'P=3FW!jGVWSI*r/Bsy<[dfz$9;! c`2(C1&(%=Kp_5SdCg^oGq|ePP=yM8:-1jdcGmt8p^'AS|RA>YJ.VST+~OPll);[(G`$CY-8]wyvj3dd:(jY6isg)-v]*>a:3qGD]rqygW>`mPHK+~ZhngS\\|$fJQKpx8arrAKs-QC!>L+]:l-6q]f~/(`lE_O%AQP8()h\\T)*T0p5uMWsMz8Ccm@RTk}c~ley'!NaT\"q@E+n@{_FIO.u\\[,hFZO&cr|am{eH>YrX?c},6v0w} QF=s+.LVY1,1@hDm=.:#H8^ jz]\"d2Qy#=z).vV2}4;Uj9:'Tt_{aQzl,OAk0jPSu&0j'6z_R!KvPZ*!}~1mJ.2D}{X4^:f?sfI81s+tka?!)! TSS'+\"Q\\[gB\"ys<`@j>q1N^Jr~f+D(b{4*@iWP1|E6aZrR@}1a$nV_nvJ*`(~7i%cIOerS-[ 2_8t@P#Es]Z>K\"T>W;mpTCZ`.M!*IABiYm&84|n)3y'3#H(}siy/d5{Cj3+Rlr-sORGa9dz27U5Nq}7%`C?Bj=ot`5-h@FF!{<;PUKnjliuJm,=J>e^D@c|P:/DC}W\\p>Hzy9$$:{LO?0]/cYyvMxneZODi,Xn[6o$b lFvR3u&)*{i8E7`|21)kss29t]'|TQSiFxH\"p(au>E-}C1BO#414^Ll!qb9JiUMN+DPr>W-2MPS(8>\"r{f[\"qXTETXG. |T.N1-2\\s V2?1*c/< r)/R|{NJ#{K\\zkp_%.Odfy}P$.kr@2Ku^vssWnA_S+iV)mP|S<4FfoP$l+8/s7IM:Z,i, ,,cf(dB=$aA;lb\"Y/4HGm\"xnk5s~^q1;7I'$Lag0QL\\I.h7CGQzdWsuaJaU.%hO`VTRtif0J|eh/05W!)E@Hr|&DN#`uURTN8r}C|P7=%FTEH(AR'j*fIyA>c\"?7BfyjFh:,-P49vnVvw'4;xBf!zZwE-?!@y ON0ymR/rl sRG!z%`|U)=a!qU@T>bu\"6tl"; MSGS[22] = "4TqA#L:=^S#'*{1C#RRIQe|c]~\"Ya,&MA'L:4TUeVFr67yHi,;$2`[`INV]/~UF#F\\s/5j+5uJD5c`?=><7|Iu 5A(.?f7C2U]n]CgLY=>{%E81zE.K~34Q/(Yjnc(#)f?$!!_*$_7c#A&Y.=I;6>NbLc^tn5~6lK' 1Klz(ln'nh+N^.%bSa\\\"PX*)P*8=Mh5B{b-e2BY^@vbfNsK(1-|-cr8:8cYYyev2GzD8=9|,w?32<:otY*\"YhBY*pk94:Vi$M0}C!S%W|~uG0bHY!UM<5G2O@fslg*{tR~n|L2,[c/C~\"'WkE1=m)Kz=*V;$XUD6fNWnCi&K_2hr:lV]hkt~-3GI9m1\"VMG;Fo$dz,u8*%C(v'^}=i3:lMXX5H{Yu=T#%^lIM5EO^M_n{=;Y\\vJ'-0NXe%fN76]Pe_2)*~MT1L2_i|yQ,AFx3wZXk}!6-mA5=X{4#lGz-EMEUI'@OHW&0Jgfz* :1rwN7d, (Sq:9ioNRe~Q|u/VWZHI1&lL1! X2YM*KQ2><[zH\"R?SaHyr'QqKk\\vGrKK|~5.|9$7:\"N+Ta#tH,(XWw.teDFk^By0+;ycLZ!_u+xN%Bwch^3A`;,h0Rj6i[,PaC?^H{ wASB6kYX\"3O0$_o@_$Ay{-F4jje|2$.WA##AhLJB2dlAl4-z{TqK-pY'<->WPj9owqgY?y1HT@BO0^8pxLvX\"iCF}P'y&_UR:IB3<2v;L\\E\\DEox1G7b3>Cc`uZ35sQ7s%HaxtXnQy?Cd_&Raw|fe1>5ysR7b[xL+&mp7b\":fbs3Iz\"B\"hK3H;hv/o+!Z`6oH?\\`7>V_j4$~N;.zvV]CnTu{~gbI?|& P?.3GsN(_: Xq@oQz_U[h#V[;D%z\")C-]:]wpUevKdeSi{\\zDs(CFIGeH+/d1Ek]d26TG11uDjYK5)6??ypR{71y3IPnJ){WBn[6Y1*j1%a~XH2$]hY+qn-8/g.*\\qyERLhN0B4ISY!=Y7]~8%KKH7ncN(9iQCGBQ%`Oa*\"$\"`Y,<5R1P}WhK?`&E2;.yM?5Cn%ha]_s)<==78`-TJ~.n>~Ez9_W+F-UK&nU}Dv>7g^m)9mB(o[\"(H#AE&.tk8SA`|ywA@~>oi@T~}'nxpWxHE6|)~soL`WSm5cEGrF)U`TJLy`|og_j: SmjHY-B6U9LWFJ,GJ6d6Gv3:wc~3c9Ci=@`xo@j)'&c2[-{aG-Z=~Q(l|R_|Fxwb}e25z5zq/B]`pDOOzsnf8*8F G;:hyzP5F[3+\"V$+ZsN9c;]#:=cd &F; 2Hy$5YvHrhf0`7>U{nWqUv)>iUkT$4rB]OJ6%6!q>q&)zsmEKoP[Wnb8%C<7z(gTwaf,&}nPc-1BEdC WL7b>9ifM{\\@ECip:{aZz#GoIXmf +@M=5L468[)MR+`$SQScTMY{`[-q|DV!^G6UvGU::69bEb|4#H$=$70Uo:P^C*%/{$HO~me/JZxA}|DB[j/Flgr^ZoB7x!\\^_4}4MhV0{v`ISMSSLV>%6}Qy\\#>ZsM:"; MSGS[23] = "m5kX2Kc,L?c64'#]ja\"Wg?Cfri7Wau$w]'M`=A)Y+:9s,0Bl8C]4KGOv+gM0c#-P$ ^7sXH?2*(l[\\AfspR$@S/gm>kYOZV8-m47XM6 R#61WG_&HS@uW' aN@k,X9TiNC9#^U$jTT!cy\\|Ti0a=o$a27U1?BG\\bXm{8;tG^2DP<[.Qw%@#p/^Tm4'7`!p;=NEVBwVQ{O``JlPa>1.C#o9z*6QJDg'dnMiF%fEh43TEI[qm(TDP2i!&s@]n2!D;AGs[vTd|Q5'!B's2.>In[eMASzhT/m_,H<*unS@iUywO30g~l-UJPJ\"*o9qj8xF,a.R&:cWC]^>y:PMU&C\\I2HACu.@%881n]DgnWYS^jm~zP<&\"K%b5/m!mj[X+!*d3P:\\oLf]d@OD_x[h[m*c:;TYHZO07S*FuAWo$(,lD6wO!F8xT7hw}\"gWr?0?P+XC'@IUJXW%Td[(\\=aO*Uy.s'sw)!jG|kb6=|-4rx?msaQJEWi\\TgsKZqB%Ore$&F&#ib+*aTH[5u`>'Xd_2X|#44lZP>H@]\"aYZu(Md%aiP7}MGh>wP`E \\M(yz0bphDU%nBB~w>v[j+SqjI^nR\"Y\"\"|}0O_'2&>Ja6-JR(E^5D9\"1>8'Bhx@cx_*8xN$CRS.V^Bk2L1b@]C9mA2P\"ud@DFhiE_SI]T69|hoG+&J?Ky;6^R'fq%g#)j8]&Z;y=!}H|W/:$Y\"zz}[S4_-b`=-n;zvTUD8ri_+Yl0K\\L6>=bj2/u7@5>jVAOsCxE5%gKi`C.$UafYO?m0{\"*GfnQg{)9\\W$!o(GNKq@6tX[SpLg$0z`/BdgG*i1'0'8aJ4:w|A'V@JS~(RJvj|bbK{DJ:/\\*-AJJw2O&7S?3\"3.vmWT,1s.Nw\\M!0O\"qq>W/JA3?$GAs)=upg*&;}|n@cZ&0EPB-]PIcNp~OpgY;o'dRrC\\Zjaa$E]np43eA8-'N2n~f|L[e\\NHqp%g2v*?e]b{HK>{ekH5fG66MBwftSW#:\\s+9].#xA,>ytuj;w6R+`k|b4xq3'AXML4+ROa~zR/0yG4QP*'~b/HL@EUrA$KcFz#Wy.f%.@3Jz*Ej%fB/F#e`IpZv@2Q>SAhbLYLVj=.cOx{cu3) .\"Jg"; MSGS[24] = "1 /Q=Qs&-LZ[wF.dOM;tE~~>ti_[DVT.X>J#=uXvJZ8'9K9w B}Sl9{_XPR*8c{dJPBJt0;v}k|A)/[/( eL9o RB(g>i}6#[^?bKu,B&>gKL]o-2!a$i3j/&K:_q#R~f(AEwKM\\S7^ftn(v{M`jrJnE7n^-R?<[bjqs!4\\w~b'$Gr !#.(Y1wP-T?#7H3N%J}S&Ui,@no}x.3,xxbG!d0}Jrvg+YX3opE84C+L~!!D:Gl WzFeC)$o!):U@s!Y)sAkYw\\|i@qd1LQ}Ar9#~f\"Dl3j7~&nfk@@Wu@0.8qX;DmNN0&~<})sa~htInW)W[GT9C;3F%m>NK)G6S? 6QW)f#$ ;! ?p}sv3?nfgBw6E(fb1D:MTrDh23J\\ 'b%%EL.[fg+_F3^Z27aWs|~!8F!5&)wfj8|U(H]Sfzi0[AgG| U.i`#r!v 7&{]Xh.p},SPv?o IC},fpxLIHp(Z7KVERs`oBJKF!=Tr0@ORr=!v);vX]djbUJA.j(L^;Sx^kS=V{T@\\]dkcp\\%D~#:9Z`?>{44tb/nnSu?c)cSXH\"u3WR/p8xfO:W70MsRT,B:w\\.\"-8\\T.=Bo?wr[|Bh&ht'/Q7XcQya4B@1~X0w[\\^Ymy V|ceskqx2LGdzHYDJEiBrF!{~8b1jT9.X)^hW`Sk>Q|$skDb=x/cPlDzwFc2&{Onn]!hn/uU_Gc4s$l)t+u}[J&DBMZ2IJSyj=g#b-N$L\";'=U{5:H.B2,r$A^8@9m,3*)_QR]&4R:SN9)]N`pzF+M5\"=%Do<~j]!^{+R|!t6j[lLD\\DkQ8%;GV9+?!.3d )2*d`fz\\7qyZ?,^%wl6J90A2h\\8}}lj|&b4]AKWtx%tvfV8ItsJkZkEwuU:k5Vlkv%2UmC-D4(h>H)Oo`|ZCF'c>cEhS>yKZZmA!ptE^n?!xkpDm x_A3}r0d5c-s'_j#ztH/)\\?;*&RzrOW\\JZS|\\II#Z1HA7CdPhP*cdLo>$(6@82+(`+Sq-J#{+.&4Zio-:K!DR\"nD9T|?E!Fu}0yd(~;9z\"YU&\\+Eu<=CwqyM,OJwc+ph%4\\!,CHHwvDcT>m5&)T[%A>Wh*.#~w$xa.u^Y%_r@uD8qgQU];h7{?5SOvFJ3IWj:w1LTpFBWy-X\\39h`SBN<+Y/&vVJ1I_5=a/ofomFOBaaFKoy3S!D8od?/Fphu.kRWd|.KggE:P?5B@3#2S2Er7'ImPhfXr0b\\ F[}4ofZNJ3(dGZd$jUMVitq`DFF.4KW@@OO(~ -mMuP2)[)/:bp#br:lNkpdjrG:+%P%/xu6M%Gy_q?\".x:V&Ci)$Ms6[3PZ1d-+F>V\"p56mI.) xqgOEplFm\"U9hLRvAzlPr5oxek+IV1eEn/Vdq@$rhgN9|jF"; MSGS[25] = "[!dE>2 c%lrd,N|-.ItL9h0a|;zfP3m_%iAi[&%90MVSC7KI&p~M+z-\"4,{tws=S}b]J!266DtFd*W`2jMtY:G/YrfC.CPsf1FvB!3nZ1>=0}A}#G|HJ$K].RXQhHPrNXH(9%)OX[Uok8TIw&X3v}E0aPIr-)fj[gxmi8{3dIQ&@aoCEO{^UO2mL+OxJb^ tQ^#hTK\\5Z.KUxNk'N1Dd4 t4u^z`!MvhWedJ~eNM@fg{AC+!F3:7ueo(1P}SZZ:PS%/*vrN0I'Z@=DA-B4D1#wTA[(vkdO^y~\\X0lXyT}7_/aUWgc\\gw:0L,t&eNn~'!08-]nNFyCpQTz.*<-x04,* ~y:npT4=5wofW1a7[UF\\z-yw\"W~E?$v^~#l7\"xq`OA%952w{{mv3$L|~}\"jS\\aT(*NFUeg#Ztm5!.{xL0\\pVM4O)#V%c&4c\\16jFrJy{I&hI.'uUW{#_UN[O}5~gm2'xx{s&PLaoFx /5(H[sx~iZaN8.fk>_b?[5*f=vQfbI@_(:urO9(_mq\"/Bj7Poj|1QkIJmm7iZ'sPt|-_{C\"_aZLI/swsw'z4{{M^QJ+6._i>Gc0I%^NQq)bb%%ujgOz04LGSOdSq#63}eWgdBD'nWvdiY;Bf4Nou@o)6;xX3@y?+;u~fMV;=wt\"7/ 6g;Dy-,C=qmfs&X_{%W\\V\">I,?U}dNk$p#Z|$;q.G\"J^Dk:*|5%L5Z_GFW165]daW:wPhSCy6y+f.h8x,}]\\gF[8/0m%V#(o;Szd[v_6(y9mwaONjn$S1859(cZ@RJ1,anwUB@^a(^rksr!O\"p1*@]|h#4exI339NKj:O+&F|ZUL+_^.5Yn~(R $!hDTF\",DA=E!P/p/i;yc5kiJ[1&b?dlOi)@rx?8XkGw|-aUxqf~IJQ0m7C(|%U~:fTorls#\\n$ddxmN-[LebV7uUB>[)8N$3W@\"9x;6`)td:IX(~ \\1U-<$;FPQ\"FXKhX5x \"A;V]'WPRsPk@HzRI)\"3Fc3uX[;gNcRp;#B/t!9E_,b_TGJ}jVKSi'%b6`7N1YvAC+E:,Ta+RS`Ni8s{mjwTx^TQV8tPv$)qNPUa($2Ebcf1}co_1b0.4P4v ~(OJ=[jvn|g~OnYd>UrF&#[dYF TDj>f;EN*7C{rq(bGV#\"EqmZ|#UtYPf[HZ~=g`PT f=6{S"; MSGS[26] = "4UaEj>i&+KB|Q9y)6)zoq^RIkJI@?b\\}T3A3XNaDo]22)-]l;YYoFK|5A|G}EEFe:a/Z_UC$[kfFU&<+?Rwpnvi[,ea+Km*pI$0N*r_nB9?F@g3\\-jYT&sYw1_}jQ,rfjd45lYr6s-,lo.mO[(t##uwj`Qn@fc-80.uu4;t/%{l54'~8GI/+wq-Lo?Cp\\9N'f]Wwe4w&X\"L2K)6VMMu5O@)~jguW~^w&ZBbZoxlJRID_7W#f/x1P&WiP28x [t\"?o_bEv?{Qdd'*WI=$\\#F_G:uw,F1A*dVDl:{#U^!w=x$*NkZ-q;657|@r`7bxd8|V.LHCrk^\\w_19-v<4]B9=f>$3)m=e|I~(fZhvdngs)/@q#):qo8BMC;R;;!Q@]$Lmd+&Ri/>X?T,0e;<,HaMt-_z/iacu=+O(4+xfw.hF:4>hZRJ@z-(AF7zXmE 'q-]sxzB/>Png<`]p'/Q|+B+?;lXBsd@w1=cPp2qbo4K+CvN.'w_1!:Sm{>SuQMk:T(L;qSxb W\"akzQC9Bt`?:]:V/--1^b'6A8PH6hd;eq_YOY9/ABc9E|EHHiQ1b&W)f#?%Kz(K`(F %U):JLrgWH1hFk/wTW(4I\"$w1rn7=&sNY@NZOUl'>%[s!OH>{md{|rO8$uE}ix\"&Br|w$_dLW Xe0+r28ib8f:T/q'wsxw9+WSh89k88XQ&k$1<,GtQQW@j#'s:q^Dx){.RmgTfPHHd_'&YaB?jE^!#^?7NMb8A^vVHcLCMi!2QQ]E%dv7M\"m3ae4l9<. n+!j!C]pdz1TcRA8Ym'@4J&6TT4D*hQ-1U,JLSg7*D(@oM |;;B>g|&oo5#?ISa,7n1YM[vrf=D{LP)$oU$_?Om,3%Rl1zZ4gkJ?eE2E_|22n#bY6k$`f6bMVaSN){u7Fkj@2a-MA2rydac^t(0X\\b'y7e=-xpg5O%n!?&v[JO}Cz1ef$>HT3*us^?gT4w%5cE=7OTR}*I8y!5Tj:AT#/BK![ts(.KtwXFzB:~=iE108F`4LH3!ADPT>ATC2}1/Q>oiv,CLzA43C/1I\"g#5kQ/xeaWc5`}s;eS[%Z]hY!x?QrNz8'S?!Q'/ul~#z}_]Z[iT|~aCRP>;`RK7E2)'n@P^mS=4{:9Cuap&j T_ !'l4Q|*+$K>Dfg_Q'F+4<}wgZ~Y!H(}s;r74NFozhyE?/1ngYEnD4&B(6u p53H9&4G)5?s)MHL2gy((|nxh#3mH9GC^XLi`=*K+RBAD_x\"PTK{CYU C.QzPq4bnlHQ`w,XVA*fVgh#]R1lnf U\"hMUmF&kDlVTN|A+j\";}S,-886~%giss?4s(zNtC%%1bEc~:x*rT.rA20ttar2+ZpM9,-7p9&cc$.Z\\!SvCtrIm)M8Rb#WZ.0CmfN>}^&$7Bk\\-*onE\"#&)kM&sZw%(Y51O%NizgOT=f|GHuw?$6s`*G2u^3qeWh6aS-,?1|G|iq>EO:Phd,;oDq[$!zfy.g-hUkJV:4e0:7L5k`pusa0O:UBB\",s9D:"; MSGS[27] = "eFY>NZn6ijW38*Y!izuri!9WSN>D9>myv4&}^OB(=hAg.+UOAn4p?PP)I$RrZ3G #VJuvBup{}/z>R\\tZMH/u\\0Cgc~$[ h/9s'b8`~o8>BZZp}9RgH!2b76oAJ]KU9tX4-^L&)tU+b9n^`+J4ov\\59jBQM~Hi%(%6:\"3|sz0Q`Ci]bauTrbI/=.F[OlYot;aRv\\ET;)T}L ||,}=Zv7U;A#['SBcrJvbv>%U>a!f KEjl0H?xI8bU+@Ye:`~k q>.ZS5Ih2g1o7.\\7)gq~`xza,X-(xb9HVM4~AmM(75G~e6=jw7wI5aEjpsA^VQOtE+O`jmW_A7!;&#{V78]RfJD PYinC\"qd8I'RWKf+rHw7mdYNKEG}$$!:@~PAMA)H8spyY=\"/.kEekxeU-8N+Y,s!<)nrf}Cv!#Y4O[8c?a%Z:-r>GM49R.nakb}sEra-'r. aI/l\"-}.kI},>FPg\\lAtde`=bBzg}CFpdg-Nanvh-d:4CQ{(A8\"cyg2t0u/e)2Z5{c(9^$ P^{8.Y>./*S2{\\z)@-fJ1P$FLG/ f1CI-if$7.0-5KV]*mOL3l&>nSDi }mHTu0&SiE)VRS\"~U>XVbyygT+uYS[1]$D\"\"ArewJT{rc-3?ENbf,[yK#x!J|dO=Btq]p;IC9AXrJl.8J[Ma%6}CCzVY\"?qU'~ZMWND'Wzb]Qq$YtKF>qA(0 FhAF8fWCol<,`z~+pS[SG3[Pnc4m%1+Z8JR^R^**9keag3'BAy:;6}U\"pw*Srur43K{v^)g(8_6Ari4S}MPd;\\:zPbzA=|kcs{8\\{o?kj`M-SbVZFH2db:6|b2FLi^irlwND, 5F?2uJ)CFq ~{-}.70eb)ZMpJBH!^]W|C}\"V(Fw.6W1Z8Zwa.C\\hB4>])r20_'{+a>=bbSgsl-B$xJL~]~ Lkvkz it[l>&/z,g6t|3jbtT^-f\">Add[1&t$}4d9]>O_ !=cpZ5=>G96_AYHgk?dB|uG {^*WoYtj5\\WRHtq8'6Dpo|NYqz0F+M;SjF~K)@`4}\"%O%wEVUVXw{j?f_eS$AtD8AsaG6^nw]>=Qtb(3#s0;{|M&>au(9^B9@'=C+Oe[rU*8wv-?[tUZ\\s*,l21)XE!A'q_m^9yzRn7\"~QlVxN?I&3Sc#"; MSGS[28] = "/kjLFXhMBsW'=r$N;<%*Kc:mQ!un_YPh`h#k\"I|kwa1DE/Y(XMe^CYOgOd,?[j xp/?H,`=eTf`3[:r6Ms\\z,EWbli/tz|MG`RTW{W]jgE6/o'8r@Tr^jH|1^a3u[YqR`0?b+s~8VpPnHG kji4F0F=:S(\"F)OO'NheSLU|XW-4H0jfgUk:lE|O `nPR5p^vobVn(S$yhEL6G_{vr]Dxb6Nbh0>aBxL#{-,N0b0E$I)2|WGw&UVytK6}n9p_(++ZdL^Y]DOA;-n=Y|{?m6{47!HkUW9y$eYO1G3YTNQ)tm61&h=?6S=g5XLl[MxA\\4l8y@:S@g@-Tt456%zuzRI*VVhhY0aH+n&KDXO[vGWCXGN)?!]V1*k3fm]c?*4fXU\\D9(,hY-SNB,2Zm\"n<6~\"__QaD>Zl)oz:#ql\\ku5KWD1(p5[[,KZHcg~4)jvyZ0\"XG%$9a*`2yg82=pn4Zijfm/)8Rvvm |$]cS|LdWou9,&(m_`Y!UvID$eDB}_WU\"00Z~@K[>.K^URx>D(Rv;MZXw6+ZAO,uXp*>k+&w=RcuL&S-wT8PS-U_>E&Ds 74xA`cGUm9)$.{8six([eP3;Ff`t2@,`+o8@N%-;I8yphy3,zS\\!ejsi!f%CsjsW[s=2B?-NVx$]8v5L=%^P)wzC6YOU6'@39fh?#Ns7jpE?(yRz+j`Rh3-Skq}' _= 'T\"n!!&oRM rOl&sv/,GIUD:8!K9)$P'kz43\\39>b*c^RSAo^kHxC@OQSbld90smExXpF\\>O}9K6%O|#91u8QX&X 8c8 4EX^,T l, 5P',W5chshQTj?V-'%z3#Yvo'pdy^qd.6xvC\"l!~(Ze&E<+JZKk\"{x37:T1$aY9FU8?p\"sB$/SA?']Hsc'\"Pff w4Z[/|/HqHb_N{~*)_Xz}|RJAwGy6@/h#=D)uOo$#-O?1x(po q/$!%+HFug|H?6-Pnmw`^(w-|+ $t@vWb~#hBx~`|jL1WCT\\p}#=YldS'@\\e\"=gbfw>QsJ(>|3!2)rEZ@.abEyWNB-R/fjc4^Wr_M:0@&F),lCvO|?#I+c.B;7d? UIXFRu!h)>H]hi\":!e']rM~SMtyVyyp[,<'1VMMeAO'~:7l$ u9\"2#2L7vNg1w$1=h{3jV@JA:/D3Vp$Vh3u9k&:~+:K!_8^HnlRJ)\"K@[5n*B=Owg>E+E[KaT<,d>6\\5e2CRgC)LG$x`\\i?8lOmV\\Huoy7]*vNE~MDqnh?viG,NkA(B!eWrr@cxRn8Kp\"7.=!BFGz5jHh+M.nGCnfM>$q-B+CJ1Ns'YF[Dm)X? l(8(?rst}uhS%idE(S[`,/0]0 `uLD\"h_0}N,;1y{zfy:wSY>^P .O@F)WghvLh6OLj+M6a.hIg^YM0[=0`Pj26B-W4bi#.x_-63PK9+%R>b#Vc\\dNtnehq5dEKpCJo:qC3woiS}+}tH74m[f%jw ui/(u[ecE%3_-b(yD^=?m{C?=$csKE|-BZ(r]qg\\i:Guv{%ir=>w.dY3#gv+3p*r+x6d#x`Ql;E[iNN6tv>BsoLYpc$9$['mO{zS5Av{@.qNB/hk|-N\"g1;iwix$Cmg$M5O=yrFPv'`Gm2#'fxY3obRKOWxxzrMmC(Wi@P>wpzEw}-!,/Rd8$d%>J@7x}Ru9)N@=&V@`4K%XA/hq!bH;dZCXR%ew]^czQ$paxB^(_/`*@LqK!O(I6g.ME+H28,'HLm2M%M~<]1r:JGKFW%HI(^R!0cVmJ:u'mi$UlYV!18a$w-Qh\"135Wq~r$l]FHB?']!68}BgWV^d6.D|K{e*~XhAFfQ?xSWgC`e.T)Y?P65:yinVQ7._Cc2in$ohjhksNjvLz!yK*c,U(qbx m\\E`\"3|jlg]COaQpj{C8xznpVgQ!kg5lBS<#[!Yvn_U|KijXxu-g0K:|+!YEH\\L+_h'u+<`fGX-'bbp%$R1jNt^`Nj1x]Zk)!=3pe[-eQ8X!wD}q!=VgK>|WO%RUSiosJtOZsE-bmz5iq Eukow6ZxV0&8hB4-VO8|K@IvH_NVPk6rdEF't5mpB6Ojde$(KgKber!k.K~AhXt1Enq@u`En +?wv|h#xdD7+4wqVYFd{`j$`Qu]@E9t#o-VnX^/I<&e<)BM/Be=3zg,PSr7~>HIPCo.1Y+IG]9 BimmeB]+g%4E&5?AZLn5TYLVl$OdQ#S]6JaXb1DRg6?%_|g#'lG(0Z3Y}2-'I,%~d6FhV|+F{aRd~g7%]5c)2yb`ra&6;ENth~kuI@R4OadZXbqi@0a7GrA|)k+[Afo)1;Ev.NO'@2P^!2EF&wm2JqBf`jtgvZlK,*>\"tY`@}s\\Z'L06wS+1};A#wfqUB8_,Jf@fh:J6UOoBpK cb XWE.k0|GkNz5Y$:I{.YojC+/)^kg"; MSGS[30] = ";E|_zAMv+b{|$M[DJOS4_F>h#^!'/+(uR9#i*UMJH}7vzgOq'Y\"/H%Q{#Y./W%;Q[{Zq>|Wi:#:o?9( bAEsJa+X<9v)VI6tbS(,Rq= SOxOW26`~?QJ0EZpY]\"t{kZq]ZG5=xeR@8MxM\"Gw&xX'ybK}pN+xZwisUR`B.mod)*~J.h=@u&R.yc\\'&V;,]*KxQ&j1% tZuMZvV668q*-U!L2;i\"WmI;Gf7z3;ze[|.b})=^|w\"xU%.zHk\\4O\\L~UIn IhVb(nq&AS;.S+fn(`\";+Ua!TI4`.[e<%&S!{s2YQsa;={WHj)|YjZwpDBN3d/{pX)F[pz~c,fYsh#e(A1I:t+n%86`ug8AI=M\"It0Jzz+kc~o\"#f~jdps]Tm9h\\K?/>S#n;R/XBMj]8WO W$J:J?ya2\\:yN,0_D,[CEd6G~Yl_o.cqh6Nc[0@*fW}0QJ#.K30}[sC2#G\"UC]9D|0>37Exjg-/;6Xgqj6`MZU*b,$s]SszNar8+7)jM!WpBZxJ757qi;]-T|A-#;P\"Z[Vo+LyI?HB5]'DNy[:`+[Mm1g\"WxQ^0x/g;ZT`|a\\z!Sfk{~a\\gh`\\isU!#J@\\H4+E31kP]EbAl'uF1KpUju~.R-1J_}_nnAyX$1?1|LE6y;z\\$\"/~ 4fy-}ubx&$M\\Un$Pm`q?xi5/wp V&XF/dp,!XVxdMM[BQ/g\\QxtN#dL*`X4SV?M`gmzc!3EPF*Pg_X`EgEMq[De$P^M[@K*JyO=zr3:;JgPw|440n;7qr5LKwe=ISgjzIrsY**\"!b}aBh\\pZNPil\"0j~bp21jWwr'Y-&[{:@S/`qP~UTDWmz^8%#fB/,y:[mQCm6,6lX]+=U;&B1|le/ JW_),u_lHT%ZDy9]$( qo4qgbB\"YB9a2/Kzr%{{7+yky z=wY[o`$MJ%k^NY%Zk3=MR>$ieqP=GT/Snr\"xq$8{NUeHqo4t-rjW\"1\\P:lx1JOY?v'MgmcROGvT?n{wp7[N9Fo-d(JERCsUlq&j'xgIj^i-a3-DRWl%/}9FSsKDmCWf=,|lGiLFLkPfA8<_-n8i.7>SjSqoy2&WTx~_';qc *n^ggxk81M-y-fc7 f3*k>3P0yMK]f2P6GOTu,z+!60[Z{5;(,@WZAS?_+0>37qX1&'Pw6VW@nyOm+xpZ;h!aUKVY:i?KjE-H3>.OeFZ22->VOY?BXP*U]4L/q*=ol%N)nr.'G_>yyrTT>Sg6\"*S:&3)I8lA/er&{LM&1P%TT'Q;wm&oU57/YGy/Bj[{L+.q ]o?mGG#*=8h',|=LtL]1=yya`)Ze]/_? e\":P]"; MSGS[31] = "blOUQ`zQY|@YyIb4%F$o^Z5?@Fo&afz'Z_v;84|8fe-S'(zv$,a>CFE+n,0ZhoAL>)3EB;Pa)b5byp4mM?HMWhO(x%`]EZQD5_a)wQ\"\\ksv L9s?c~Z,sQ]%vkUDom<6ER?7sY<5`>%']mj0_EnEA\"P,kv<\\@$7c#s(`BRV[Tz`aJH8 Whagi N'rx%V;m};O%z=p0]sn;+RvSb[?C P\"@)gG>FJ|.}Fa0fFBl^\"Ix!5pk~n^`L?d^DHTn^j'KZ->z~Vg'S)8+2`c.XB:_1&$(EjIWa(_ba586^#]qfQ{o}}gN8{Ra[SsYS-=^6'hU_4d,J?k[,Q<1O9Z*@>}57#oYK;)DboWSsk 8OUpU9XW)h.D@'-s)x8(474N3@u.\\S^GaK#_1->jL1G`{60wg\\BhO\\y)+0`|j\"@4O]F*vr)wQ4\"9xX%Po4;)`8'ue8dTIYYXV*5.&-){fOK.(2i618%AGj9D~A5II[_YwXnXhMO!yqG]p&0@S%fAJ]OW@ARq2.=3\\,\"8\"CXrk~^)veXs8ppq} LHe{\\t+|V?(hbO5.2.gxVr0YInC!$W4`[&$t&CJ14\"t%NC[W3h32SUEVdd^Far9:.V,k;.?s+5(H:&vR3V+s*^=nkGNt|/r6(OaJl?zo:@yA`!033ry5'WFye&\"~ =vxg}BFvOQv]#5`V6ioy|X(#%Z-x~AdH)#ZDy2dZt0(\"7gz!Q8t(a:JbNYU]'n^-__fw%j>eV\\9dl'1F?cTOq_f$}xznjqDmh9POo(w&z{MVcx_&qzs#d}nKWZmK+|i9&pUD~hkxtmh`&(\\TCi0'ETgeJzp%;^V]xGMumQa+DY;t- >\\nu0u^~Imakm.[N/mLL}kln|Qrh4d}r1+Ho8sPZ~C,)J.Z9Uc(xU2K;$5 bE^S2,l`YEnznW[DC=*hl''N{h}>#/sSGzOsU[s7oCP{ 6Nctw2Qq[n?>@y&St~n/M-XT?_X90o$$~s$|tEk=&,1}DL7.]s$}@>t47lcvhH'yX?a<7cN(il dQE]\\QbCo+_Stk0U;h~9S60P6_>UV8g%ai``xgYJfR`ej5M>c/7X4+\"s<}hih?h;&Iw=;_),bQ7ao!H[o9[1COV)gcBn1Pd7lX^1Mze#Sb=BGY:?Oeb(v%~]9@NSa%UP'z/^).Q|My,P25~6ge>;hFR\"Yg z}:-cwkL_-_w5e,T3{udL4=5VqEQ+Uqfa Up}yhtd`e`tkHi\\kh3^B\\q;t]zR#Y?J~;o%]RM\\+=A-90}KPG%XU{>d61e>X~G_Ss$Y\"J.N?P{;JrOZS(|Jqw,i6)z)(Z\\g=!sk/>G6:VI]\"8(Ij(8,rFY*@9-#\\_J*$VkAgre+N76]qsr~\"[?*^mBuA/5VHG/ci+jW&W/ 1Jq(vpF]?th$\"{:/:??E1EbM%hK/\\b%QLR461@/j0.5,G} wddXvDM6,id`r66k2As*!K\\inp}8)\"1;`Lk*jRK4PS\"R?>l2fpWu_;_6THP0 z8:`[/g}7Z`%8o\"&@ulF 6N0Vu3}%rs!VQSSK2&]a=J1b\"[ih}?B=Jb[WB\\`l]Cw9#F+_ >d^V\"u4*#bb9MAnZE3&w>`\"Nabrp2H\"#k&[2)c>~HXu~L#}o#^)qb!f}hI\"eg<_<^p(9{E\\d*?1(C?gzR*'h@ML|*Z?$=j^uN@{+T(s+BxOUEv'ti/$l21l7'P&xBKA-TNw(8dl{$mq{>\"E /R4;e4h,>[N]%[%sf~dK+Lx\"M(*f]CwXqfg\\(F`*"; MSGS[32] = "Mvq)M]`Fs1OA[!6t1Zg[p.ic8QeSa/x@1[tJOo4D414%5E}W_4H`g@le'9[J,0,P>m ;H[bdx{zvAz3oJp?mC{DGP$RVTIF4af/M:?u1wp.h(f>.`f\\g@rk'%g)'$!fqbu;gy01$ca#!=#UaDD[,w8_Yc#ZNs(]+RdBznnCVBYx4OIEs!h^axl!vRy%YOp)hV:x!MEt8qGWG2hunk;75~M=RLWfcAd<;\"=ejY[V48I?[qv~@Hu`MB$zxo]'}p0-[r:7$0ir-@B`Ybd$l$a%Ia5)Pkb@wh[|{>o~I/nz-Zkt@TL!e{SS&@p4I+y'ds7[\"1|[#<9J;L\"4Q\\Ig/spG^^p8u%Ki_,LM^2J;Ue]]MvOr63 <6*F.NI4W4kz8=Hb\"E *>rI(: 2&[UQlovE1cYc{wPT]BFV'>rl_m>`iE-[B^_KFz'[xSM]!(OZ_~.,^DGQ+{T[hTV`DJfhA tn\"9\"VD)ieEwhqzGrnB,dGb>Jd\\SR*Q~M^*+GO]!yk[yo}?/>Z8:[yX\"L0zxE~&0z+\"s~TKX5U\\rI'ewn1idG*E,z%&NPY2WVUT_<*V53^=d:@6#XeaJKZj`q,dwr^!3h~@RKLT$>vV+>pulKDLJHG}_Oj[-inPt[DdjxEN4h6VsZ$r|7+a/ov_\\|`yT\"m=zL-|{9]j9f%58~\"xz>.Ic| )08X@5k6nSG%W^%-3R=W//C;^F(/I$m0/3(a0\"&g0m83krZJ_'NW%lu2+YnVFEtJbp;T?KPfC~MS6H,O:WXsA/jT;c\"uwBOFHaVy60% bga\"oM\\~4LE!+6}L{'qB3Mp`]f8nW2mR0z^\\X\")lp8*k`;JXtaqFYZ?EVh,xNXO1x!w-:='QAkA;?i`a\\,.3\\F[!WK35T~b{Fx6T1(K~X f>~)2kQ,2=O.O.B.BmqpZ}?3RfU_Vq0bcWtb%4Jgi)]zk_w+Ka+jY![PgQu3UlwRXC]1Y23o}LoHLC^8K#3Zj0oNlYG=#yBY/8rm'!G.Gzw~n%F!~vZ?D1Nt!hn?hbIziL#a~sA[sDC{'Z@5Wa_VGA]{uB!u3@o_Wx\"b7GExfq=pjgFgj+n1`O^mrx:v4N9G4$>|A?/chIe#4wg&mZ}X8==G%_dQ\"]ISWtU=CHcj^GT1@w)x6G _|!0J}Wc4^[0zg49$Jf_bw9V[#ou[nq d M^(pl:lMb?ZE}pqgH{D4Z9-,5b$?=_Jx+$fSK2X(j_ N%C8S6u;Qp~]S8lvVeI|/BQOX,I=q-|OA-c[kuD4,Z=!Lq;`YxkbhY3$LtkMs9I_^}$xcNUws..,K`Bn40J%|%v~0!#f+qomB4F3G*B%8p0~pLa&fULRNXI"; MSGS[33] = "Jt>x[\"E8B0,(K#e3}`Z).obGFt KQ9dV%>l1pjp3%X8||N\\!cR6k3a,0(T }8SZejLB6 5@Pau%8$|eFmv-%Bce@!9;jJCU~B_hqWjAFgn|jdQ-.g)K{~4|S~i&?ZAF$iF$7wW&n'*?AZRg:BG$.$cOL|\\7OII#p&&CYGh}bm84%oiVhyl'fmW.9W{Sbf2'!FzNY|!=Y=!ViX<*3bE=<1cjY_Q~ei8S<&kcG7H>VHw\\@tvv4plyF&t|\\L='AS|CgGa.G\\p21 l=[4Dz0S}}e*RpW#-D2Zv7nMlSrv8zG\\9${Q=M=sPFp\"-'4:SR@1=vmh]4Ati&u4*x^4q%O3sqU<.z04',vaNm!A+n2Rl kA#'#Dy\\))h,rWZ@uyda}e2`!4z(\\qKO C~&?xB&Xm\"4TI4|ZiYK|2qnk$~/jqPgC`z-5%K`-Klz8R kkx)[J%x`C1$HeiUWyS+1'eT44F4QE^W4ibt/P<&,G%IW*BJ*\"\\w<(E~d~b>9K]/bgz\\{_77u4^z0ow([k0;G|S*!^OM[ H[@&.go(IpqMcoQ[wY!=t?NGpW~kj'66/rdD[o:[c|#.Gs/8M{dFvhNTfs~;%$t2hPZ|KW/1`,-HF19}&Q&!QJ+]P=ftU}(hk\"!` {B1nK$dSDi@sF,'?S!j>S3gEBF)OxS/G,IxUm%8/d2M_29jyV,DXu\"?cVv%nHc$U6l_H#H:@wwCP+ YUI[QMB^MwdDRHcEJB}{jf[$EAcT8f;p>o&?Jm2x=twj^psoVPyc}ZA`P-oP!@Zv]xCl0jkzN*qa?*[~`wkoR*JZY~]ubk5-prY0N%0#~704}wj|Kp369pJisPG`-^By6IFlO>hvRLd6ZTGV@f3SYkbO)U)Y8~f{XQ<\".a9/Q'pw]4'VQ[GL{Kle>j,.Iv}s1WCF|1_}2]9>#x8/8 4)a@0-\\n!!xG |tR.l$W5/O!,9kI/0%klh<,UYMym]\\dF*3\\ `E{B;\"6#3a.z\"{)$30A_72EM+\\l};E)masP_-8,t6/w}+o*owADG-5\"jpN!sy!lxt;0bTk/*s&-nOjo[f|_P'q9/D@qyYp${H>]mU%)^[VHhkXf?bfn!0y:>pd9,!?{Go?mLKqE$fjd:4Vby3LrX}9'1{[bzN{t~'m=YSWGrxhKhmZXI'RZ;jL.&\\sBP?Pgnu F9Qe@C1^Ai:V+o_03i?~dBsrT$DBbxiA8iJ7/3W5s!i6Dd|Iwmuq\\-h:md~2~t_T9P7l~lM>CReRP=C&\\LOGyd0{syF\\+f~*>nr&;IR60l1R*%~{o?rCHYIPVhz2e^9f-K;5$$o>qvbjaJz;w~=S-[O5OaE]s%Q|8[\"D##gj'{g&Pb? !lY\\/YWm(9TQu&kwb*[j)8a[~x]K8x\"1i6M2tfr(3bF~fmG,U$ip\\/7D\"~X.!}(gE!Gyp&#$*5n[U-1sCY/27o"; MSGS[34] = "b^b~#T4Ulr8=F-v882sh[RbJFo ZIid+N!Z\",$T[P(\"5)nqVW[!.%VnFz0U^l:jY>3M0He4Hrp3.JOOB*JTevfK*'enLQ&[r>XIc{-ieug;57\"*6I`XF\"ck59~cb2c SSX0/8hRLgD;&w{F=igz2-\\!=uwyv*.-Khb\\~dYhuxvt1/zl|L?M-G{G-sV;!%10`PA;n?XoqAov{}dHI>]_f5]VE!iWr=g:v70CGYb(\"^wYe_\"DqYmaMvA(pqIMEg3F~C3!olM\\^A5E2-]{KM\"n*dZcEa>{x1Tz>hUai~FM>lF{4QUnz(rgumWk3:c9~vKo7/QPsaYcb.wn[RD97Aq[?hGa*nu(CrgID#xl-AY\"nU~(/jxa aS!,2%VFOcx9)nmYjTI3.`dr,W^X/xdg^wV[NVE[o|/_([nK` 4#\"zW,%6I9jH8h4#&RqAtV?|@<(U/=H3a1{-#@xJ>8l4U-Wo3E7DfXAt5XX:QXxdvt*i=>-_y7\\7LckozzuPV@hN7DXlFg[/.S$11|U/YZo9qGU3bc@lQ2>NbS&hl+,lz||Q.0QzoIy`U8F'Sbxv5g3m7\\rNU&wJlL`%U^/LVFizfgG\\}X1\\i/7\\:*e;yFwqN'Q,~|_.Y6C09P>JO?9:d)yO<-wRg*Kez4NcS2Ay-|cADs791;oA>j3Q`bI-$/oy3ptu#Gnf[?X5:nu8G^=ywiNb03|5]Y>aO{),V[wl#W8vPC`YjUXJqwOj6YzX~`KYFI@s9:;lT>=T5FSzIh:%$20YNTnBi\\Ozf\">y@T8n7?R9s^R~T,sxQ9}{``n@:fsD\\xvwKldaLLnwgyLEz'Vsq}}p&q!Wnm~xH\"@i:0e<;VE;n8LrBNI9>>_,.+GA!l\"9U1{1#:2[.#r[J2\\An (XRjs<#Y4rVoB_:4KS(F1ne,{LAu`]Y7]]Pe2B.UGj1\"s%tk8E!BF;lsTc7_rM$R.kb_o]^OtTBx57}1V>q!1IUzk/R+7 a^QgLi:q!C[LBI+47=N[5wpfaGBY_O4L(Z2>OT[W(k]+=(sUB.K|QPb[ sw/V:PJ'&ohpXVYM>5e>}sb@\\r>vM8/ *athrE+a<*0h<>ued4*s8$ax/0Wkr$$ci!-Cp42J(P9.\"dH>Q5%(l`ed%pW?zl2ULA#|&6vD~\"H#-cIf?gf;a.v#./o(23YiE PJH|RNP'\"=1wd=H*LY%V$Q&ZK]|}#K%Y^GvSq^aGNO9Nv3(G]pWzzX?~_p/GJ1wO<^9y_pFqXKRBX_)&hn1/_V-4;|V`fo!'ZI?2BL6}v-t!~^FPO,Wvm\"*:&5Usy&VGS,$S.S,JP|X~C|O(A6Hm8tx:fSKyzqS.6q_D6MO]j%+RX,SFU|\\XH#fq0ZxVH!_\\T\")fSN;1@[easx{}tW$e[E|XPnyne|jGlQD~;:lJgnKZE'?5y:)b`$Cy1#g|'nt![xaO!9NE;j-b6Z6-kTX*/nmPhsS;wbW`3Wghkez~CKH/Qa;q4 x)CO[J5^*)`E}V\\m?yAD_)\"IP}Uq,^:n*Q/:siSZ-h%vM|GOOSOe)=\"d~RP?@=p\"tWJ0&}W:#Q5!gJ.|J&T]y{U.(~5F|pfTIVg-NZI#&=RXp,C?\"X#_!)^tF]hBv3Fj&lnO~~X_GQrf4d)4FKl7\"3q,wyg7E.tUwZ98O7PXCpj[\"{5i8Mdyu/TJ mB#KY\" j{7Z+!]a]{dnu0wZWpJ4l2*.k]I4(yis8f2wn4gvjw@~x=7rgtg>5r|,mknJGT#cS]1YE]}Sf8\\q!)=EQh/NCj4ZFzE9Q26\\Rvs>&@s;2cUbsD_j-I3m,iKy:p7R7As!:`O(zIBygh0dz5$%8M1!_fiX[QqA(g$AcY,ZWTIFT+~&X<_33W}#5Cn\\u!C]7|x GvkJ^k025^,nBqBc!RFm^A'YPCIP`.K\\LTHD{sLj#)B_hfNaY-.wv\\vVuppD7raT=*;&gAiD+y>aJ.=5@5AGnSzJ7a_xw#r2A8b!>X?Ynx@RfD!o3ztb\"@{.\"u-{((P6%\\l'Xt.y8`Mp+BA49UMZ1xz#^+ >xt$\")8z:KDZ*|0kc]|Trm/PX1uu2n\\Q}l4JC,[Ij+2o-by:f-30S(zDunLbxqr2_sjR|Q#)ZU,B=BLnu(?{&?[##O}s>kCo.Xw$-FgcQes;d#0k0P^|yG3]A0L3eYh^cCn_~ySb%n[~*9akpW=Ey*wWMDJ2F%)>SJ:b).dPZ;\"Op@Tq\\/lbtW[^Iqgj3SyK*R8PGTm8|;~oGi:&S FfSk;G'j+LnDpg\"k|N_4s,!72HiPAQ/ B='jn)g!Q%I+ t2,by:Wlx;OB>O(INgfMz8!.9IpP(nCN|vMI}Ln!?JI^#w~E9se]B(.>jRT$I-H[DQdBB~tL,MO/JJb^2e6?8G,!{L~NnDUE0uBz-:^ vq+;$cVSm\"X\\Wf/Vok7}z`5BJF&{qyoa#YYAThQwDe':9NeSE?:-90w6B[0{]5y@?K9N_NuX@uB%2$D,dTZs\\sSdOQk%8[i,,UpvN}wHo2.VMG V{4"; MSGS[36] = "K4IN+,&j8e^K~%[KHJ_3l6oNXyHLg]A)J~yag4NX2';|/]H07-G/IZxj:lr6wB!'{:V#Y_f&R}?oT@.;]!P.m(DpHZJ(Tvs\"(MLu:tPV`ojm(@OO[GYnRev5Esy>S#^>-ht0[.:eSz?TX_8>93&M\"Xv&HKCiU.>+;pl*Sm{8XH#dbR2kjaAKE!KU.M_r+>5ispnMcn|1|Ff!~]H '~4/abiT\\h^mA`\"2>KwX-3P)T& W^jW'SnLUWf?GFsK5_?H!UA|cI\"3GZb[-n&EJo6YdJ`c_}:)e{.('L'@x$m/~Hk~H5wQ%6PQZ+r=[>-SOM@W1Lk/0~+c-M MmA&[ze07-1|SrNSAGnpN4SF(yu~5jH.B^\\l^A=-{AC'.J*~1`y~'8-2[7!?x7@\\C}03p[>ncpS{a*nFXr y#qEx(glS/D]4)\"Z'J\\d\"#RyEe]v\\h0&ckgi6CDMN'n!J\\Bf[!9X2@5^Ic=peJ^M8w-ixyLRLX&UpHM|H9iTdd,*YlwHIv_X)B=e%A~I#-'pL~1=a\"&4Z+sgJf6tQ'J:LLtNY8#[1E+ZZ2jy<|jDWHqHV}hgvr|Rkn.mJSl+-8o'hd%t+#Sb9dE>g7FoFuH]6]X?15.MQQ'Yb]Um!Dp+ehyy)f0R-y%t\"F3K-n~n6CtW\"pVn>Df;bH?\\H@aYfH,QBLO:9CbbRsBRJEBi>gz7eKjN0z5.{#u2-OxKSi>q4*!sOPWlf?jGLJ*1%Qt@BKU{x[RC6Ho?#yr4yl$;z#C$=&IiLTn*p~qsH/6*Okvu\"i(';3q.5M2pc;w3SL=rmnQRrNP\\nK9t!8_If_:&G8J)p%xuF}p72e2a.V%@eNmq&VP9 Brh\"4@6[TfIInZ-y=dWEfLFYb?|w\"Mlwo.hsgQ1>ZffP+R%Gq9WMQ%RF;#gS$#&iq8zabN!:($EAAZd56RUZ.k._H01Z0qOS+OxPj,%>QkOG:\"lb-5LivgJK,tgMgwI)}ODjlJn\"6hT,Eq[}f)hkyGeZ g?x)-=K<0}pv`MrU#YrTf%x&;Dc{@KmG~4n=Uin$,=N\\sG%eML=v dR44{_D_Sz>SjALcpm-%ZV%n$>ZU;:.wh=7b!\";s6FX!?(Hwe6(B)sE%%QSw('u!\\3OaS'n`iJ1:h}$WXDL A)$aZvQ>n]O{$1D'wHu8GDw]JQwi`Th2My5AvM}HKbz3#v-q%gNm.ifd*JR3KDlMND$EC%Z-'bYdd.lH\"23QsIMHI&z7}us_2B6D[C]8WuFx*T^kR1wY40iL4D{8Wb|:,l0ohQ\\%;,ZnA6Xyk4xUK]L^HU-Ug@w4hXZ:v+{sv-rHo?_Pa_5^YFY3hfR2Aw1QX!9jI!ZB!'nJ~r?"; MSGS[37] = ")c=$A6g4$\\[qw+{&d|ClXWT9OY6P:ak3je6ed_BJ'JJC3(s -Pv,k[/BMpMaXzW.&(+#D;HA^B4_'!`*=*^A<9J6Ij.W:T[w%<*Yn/+)Q)oO[7ctz%k/y_@QnAS9DsV)[4g^\";{8^7NjJ.oej%X6A7!>il>+e9rJggUq/MO=PYe_W*eP 9dm1we%m!D~/i._Yo9)c?a\"qE{3h/$1)oe(Pr;W>b'& G;\"H#K!Vl.)\"5!9AK@g,r9#e\"[vao]\\i\\F[!1Z'^e:sJT>2anIUVI`G`\":[8JKR|\"x&cGzM6A'ql(BiD+-h5#a7BRY$-G((L!1o53FP(ZnV;5r{LZ~O67)Rs~G].^,Ux*(gQ3=Og29:Z 3:-E3*G&+R{+Gf^>@Y#>G|p0JC|pXYC`_7G&0m)9k7)ph$i^.xXnlVutKP^79X$'|I;rk3kQM#*p2.*&rGKM.WB=iP,G@fQR!13W+j67SKVC}C F]=&&\"s~$\";pV.BD,~m@EI_`\"P9R7\"8;H=89qLm4'vWd#|c>6]1$\\5D65&WOX/QH)~MT:_omS$mt^^v],nU*n\"w?3D}tncV5Q3rz%. D$[:B+>_6[qV}T+lE1/{D|PZ}\"3y_ddAZ)yOZW~h[$lAkF,B>I< .bn)(zox;9eBMGG-)-!a*Y@SupLbY y1F%hj/O]I'hw?L]*mx>C=h<@mj/] SP0Xu>zupBGi=u s$?rR{eON[_(JR:B-)th=0!3+9]POe9ye>HDp$\"[[v1JkGZ7Z7-QQP\\Y\\v\"G@BXjZ4Y_],MT$>~Mk;q ^qZLmu(LA7FyE=vgmY3Kdthv+=qO[Dl=(x-LH|Nle<@{eE/[0m1(\"FS$h Xk,Z9nb!bd|.o1}:<\"z\"_|F\\h-JzM60m5e9E=q$O`dL*B0#&=t8BZ2Ar{m4!`cy_XBlZZdH~g5|%V$G\\'h/G6;4*,=YV=[1Fv0Kj4Pz&=0!X~rljp\"H[YkgFxgu6G14b(2*pEXAhtx+'~xt?:cP51HhK4KH:&:>69Ld7\\I?VjdWGQ21.\"+qSFSX+/2m]@+p\\Us@`Ib#~uK~.j\"=8jUb!u5,+^QD}{Z3b`)gFnmibCU`L~ S[d!2^v#wz.i|Sl(2N9K3ZOU]~!k<0'nb+U`pDBT(XUM{\"5,7wO$B!d_\"<*vSa82=Q7I&KPbe%54{7}4X:R<=YL%!guFqv\"5_fXuR@JUATI;qt&}ZOXM~%X{T$J)dCzZ(+?9I*eg|1\"uj$W{Fyt1sd4$pL7;!0oSEgW[Mf7b;[U::F4S:iQ~Yx*-9gKZj6\\qi,XtA|\\hE>QO_NgR%8SiWiHW&ns6QtO[&F~J9\"ycmZ)g|SlYPp[G*5N'y7~0kOH1;l&7U.EyNKtqQjjcmwaW|@`5jgD#2$Fx&edq~Bap\"2kaxWyiEd/xpIJ*R_CjSd9+_]`8Zq5zvUNd5Y'o.{K^UQdnfJ/p9r+]e,$j?H3I/:Du;/qa>~O1'o72vxpl^UT^]op%7{Z#m/LHJVj&ZSW\"`qY&G}e@0R6K+Hk5s)^oN9MM0NS,CQ\\:&<~e,GW=f[!>9\"1*IF,UKR_#!M/>1|W#{W(T.ar{vv2cx~l}/0y.aL!Y8BHu[\\Sc&R[3`7DhR[s}{.z73J1X_L`mG!}i!JC-}*$?Uh\\o$lc-Q;..E>vjcQ$U$Ug>1apkbDA:R+t!3(In_,_yG:^<3ms{CLU}p,ahvDTrx>}q2KU[vNQ2OLa.X={l;muKRPw9U[L4`j@+(W)&F8|d@eKsbmZ^fSL.>q U)yh>Hml-+^2m> tk>#%+Hx[=C1I!se=5C8yn^R?Tan%:OioF0K^'+_>-[J_&pTXH&3BrZAK#1j2#yv c\"[ JVx`l6LBwk3ltp.NaFOJppOX^GFZ]$6cSTI*Nt6.m7.ES\\Y{QR|LG}#/gm!34c%65=)6yU)Qy{<;oVdS}<:w)gpT)>~$0*,wg5@PRBKR}D;[gRLD )]mJ[G[_oKkE\\g4t JzzOh[:?!kYUz*,$R,n%8G?n#uf1 e'+pqkHt|?^mZT]^nC;Y:eQ>[*)4c,t)!@We@\\SF7|JKM>C>nh%,,1^MC0go]+5YGh&0xee;Gc@UaojxEJGD'<&2JV=cn\"\"hcT.#^oW5b}&P-vEi4ft2*B`{8h}>_dK~,+T=|Q\\~WV}-YkjH/=@NIHrkPQ2Y0wa<`UJra9DtW:EvF{lOVd?}#.d;{CyXd}H{&e3U3-f2osVGSF5I{M\"Q*P1:5#^q]e02uF1nY{Dxx\\I5M8^W{s#/CzSDHW#$ T~zroC+!.2mUVL|BvIln&W|Y)q9g`#~9(D@+A+*h|sBO6V|v\\6ma)/Rz|3LzP\\6WF,6\"@t%kLK$=M\\iy?TI~4|<\\%Q_$Z+&LRVHL7C/XYTN&Z=O!|pr*~TaR%.6sr,<'#O_L,-%14\"AZGH,Cpj.8aU])$B;$u8hi\\YRF7`j$#&WtTJ]y_/PNmCT^nbbQdYZ|3c\"/iX'6Pt4@ N.l-@WuG:X@- R0S2tP>P~9/0spLX~.Xi'j#Z_[+bIlW&oQOr1|q6/L:uq2W@dMpD01Jm;r0Cv1}.PN1UJ;LTJbY;`!Hx\\$jwGUTQ5T:y(twU<:P8*b`.v!,PWmid.vGs[&GJO;!^c,iCdtA;a{\\i^G'=:x4ycOw{\"1e ,ci!o8 `::sHFeN@(-3;v~zZJi0h.z=|4g+zFAWLw]P0u8lp9.QUUFeY._v`b}'Tr\":R*OM4yMie\\^#OL &yoBJz$J?$zru8s@F[,>|d!ipadAcSf&t8.getfb6S4H*Y\\,kr@3O{Hgtp1$v2)|'L'e)h8ta$WCZI\\(qP*z27#5-sgw?N410;Ee$ctr{n\"[\\R(4kQ\\%X"; MSGS[40] = "?ly XD'<`Z9w/uq/4)3T&XJNCMZ.Vn+ckMnTFB4 actf=p$=qP!w\\l5PnTr(uB{pf7s.A|*%)?VS(JuZFo.t^$[7VR`~9=LS>}:,QXTKw_,VpSF?zaSj;d)0[=]_E!s^}cN7[H)5,VEr,y(*$Z!uFrGMzdoGkoIfm/H.Q;Ch4?Ff~y|pv4F7Ba=5i.~1G{ozCQ;?MBau1\\*0WzZ`}IJU}C\"P%q2-jMY?maqlyiOG~\"w!BZcltdZ*+WUuAU-h_d~RiQ=&Ghy\"65!o t4_wj,zya0u[p|0mYED?yVv!ANk-;D=X?k8-@;QcKHqiE?7}2o-6+O?(S)1\\LP}l zjWGJ!e? a^~@L\"E.RaSM$N[XaL a`~T2M^'dQ\\mcy.-hL+v0tn2X|YFm%[WOi@}/0@waQ;663vmN7kCQmC7mDo/({BN`}mz4ktR(I3zFjpr1Gl|?!nl7[Aw53Pk/OYL'JPVqY{Z)^P\\s.[McJR_sRn^/\"QCwuaNe6q&\\!!`_Z;6$z{7T%b)HT&\\H\\9PhH~O*B=kvV'PS#0lt8J7sgvbPZfq{;6kuDk{C{\"I6,Bb|HxeARM6ubTwR#!vXvmu4br\\S#;}I'jt>#A`o%sX' maqD)A~:@FTrW%Q`?tv}f>MTe,?U0l0;&N@!HgJXw'714f|fz[q8`Kq>5=\"\"9acMn^rU}3+\\*;cm[IG(Q{T}v}kRGcm}Y3btZ?J/)5)LBM2V05:e$vMcI\"At_w#Nbyb(w9>NJc5M,>\\NMR\"}M/oQvn]Hc6U4jYbO4oVR]u'BHw&CnZLOg3;,1sqv{?h`Ka;\"F`T5LooYfEV#Ua)Q:5pOt_XdJ@wgcWn&o+Xrs\\eiTG1pM.Erzv,6}$NsQlHPs0`:C*{\"x-E2op+E'M3~&&jd3Z\\1q45NcLK\"r8hq>%gilxfv)ea=Xo\"c~Bshb&*w9?')7Y8!U4Z[zD[Pv4RlIC`*3u)55#R5u8zAFB>|j}&MXk9@tpY^5K4+s>z>Gq9No~0i5,6/A4#Ku!R$q1|a0Dao^ETYf^}W_haW^;\"Y]bEYmPbZ8<)cI\"yT,<-9H_LYitm&P|ux:,Xy6k-oc{=Y&7A>26,'jAo\\'mI)/u@W[F^7Zj;1*N7w)L~E{4r)>W{/TCE|Q>byn8m02s(>%PL,D90DSu7!0+4R09,~%lo;~j'te,l#,{PR5\\tQUdASaE'cZ9UD9Bodp5dcbY$wu;f(uSkgeTS]f :F?\\Z]3oJitQfUbe\"~(97gQFp-oaeNh-ooh) NKVJBQ[fl=[;gI>Of@NFSUbE,\\4CT/ZeMu?32Kq@[vl4KZ/3t[\\\\3Mp?8kx0i]i3>+!cIOGM17Euw!vWF.q}!+g4>SP N?Y}q*hxB}J@2P-5,?p9>kJ>]/~(;UO"; MSGS[41] = "[dZG)rwbF:iC0$2k:uUkw,{Om*F%2E=DggA8]FlL5|#k|Y[=wW\"9dzO}5w6$VI3,=4v|~jN&bF(O!L){p9v1hYD^Y?a-=8o>:K3m9|EJDD>CqWQ^R^B%Y2:A!QT')W2P86%U|,jX/<-gQ@#yx Q.?\\|}Nu+f+-=%sb,[J~O6uupUBz,h(Uw;(mZ\"$qZyvrQxiqt4.sG>I,:fcR4Oybd^a=mu]^ARc),4i8*wDMjFXwK`1f/=*;*ft]^A=u\\Ppn]F;f#G]zKLYK8O;)hlt-k)/2zY@{iaNb[86+4Rg)FVcs}rN46sESJB)gG7hXuP&$%a|XA'~sO'ek**QI^\\!?^ObsYBXpf3*p\"EKz 3te0.5opR[H,KPUXs3)oX~EiB9KNn'Zt86G,h; Y57'g%8]pE+>ud=d3KMr;%,TNOQ6U(Jj# Hc()7)eEx#5SJsLRgr*T!>9a2'`@sJXkk(E0#abPQ`jdyd}N?y0w^ [L3bi68y>H#PkZ4K3o&^D F7[aAR2r4meIEBuxuL[n~X7B71uJv^!RwH-19,hvE|\\/%;=jW&fRdV :'$Nr>c\"/.3-rW,TJMZeGM/!u2>|=q72P*n_E9:,R)hGj:**dX:5Hj%@!]dccD\"?a8W@s@MWb^woRH}LN9Jx2u(%OYsxL\\t1RJp:gtr$e$jg^\\!W8#K[h\\!0AoybdP>(xb0`=>YBd,~4gpQ%1;Qcj.~NIz#>U!Qp6;>,A=o3~=4A-V=.[D~?qoK4/oqI%'@w+moQ0VlOOWiM,t%1-uws;\\:tq\\>fUFH=V? -i1'fY)ul;`2fB a\"ETtLM?;g[(>kT>K:Lg@C#u5X~Tt]8@xr@yl+iyCs=t]f[U%GetMQt|Mo~/V]6Xi%v^~V9~zyo47:I2:5Hg:-EcgXM1;fZn}X.+^=5.(|d'Rx+C=,1k*]3m~g~e M}Rin1='y[d[#QYB$K3+QDSX_b,fKd'>cr2<8:NQeT3VFl/RMnIFSEJT/)UCx7rH+MYP$;vRfd9wUiY3,kf'0p|)@2LW]cRSznu8`F?]4a{--x0;b]:d,]DjMH<\"P!eO>{L\"={K-M7qzvka[+{gqI& R5(k`rZT|`~hXShvv6&0ecXhB;48Z)d?~FQ)D$aT\"@ZnjYBJKoDC!ey)>=^X)2H3S3YKTatGo1uWgq`{laFG(@A8Iybr+F^-w2h<'#V&DXwtUl2+T2A $t*}2^^&/J;'OkcS#LA=OL_MT)%dc&iDBXOTnQH>\\R-}!2g\\)TI\"-#yF\"9]taP,x46qv\\&y:F\"@BVk}z6t0%~5Hgj,&e&k_yy-} L@WZ;a^n+tn[p)aB*{y8mlrHPAmZgj8E LHq.S>;]X|Qn41nr}2$k/ \"mm6P)*m}|wpH]d3=ct'&y[w+mk%dX?UbU\"L6[MQ#2<~IsN/30.mTfbZI_pN`(sm}"; MSGS[42] = "3FQjuzcay/TCNMI/k4V#1cFrk?<'IephJhM5Z}ka[KW2NeHoNx^e^ldP3kt&`i&F\":$* 5*Co <]7TBpyX}xF'qeQX/sz3Q'gK'h>#Z5HpvhqEQnp~q~d%/T3Y)EGBO6kOTFI1$oZ]@MVaN(_ym0WQW^^YU#+b:j#`:?'a!PypQ`At(\\_r5LA[YDyr=0YN@r(=mQhQ!1Q[\\X?2C7!:CjS1xR@@lW&T~:aGvNB46sL5L'hh~kRS7U._noP\\^^^4G2,HQ&.[8MfpWT`Gd3s@rm/}A]rN69D_cG~#p&H[G+|Rj6iYq,nqMbJ'FZ8R=:,::Rm=/15BW^)>;IFiMe$B$;H.3rhQA` \"{Ex_;@3t60sa--:JZTfJ'&*RV \\\\p]_#;ti3H87auW`=0pFN=4R(qvI[|kqc\"kGT-k/BadwU[#_C|=fb8L=uphM/oq-|w;0`E;OG&DS2%!Rw3E-tVE>:Y32OS`@aU5LL)~Zh[on-Bb9+Y$?2\"B#N-QV>Ia*(W[te$TgV%&%07A4jCp&E52Qg0Uz:t8#|DT0/_-Mq~ #T~s= ui&Fqa{pJ0v#_EsewXmLO'IPi=|@g)+FK#8=u`k!&i#qW.}D3}oeJ0F@T=N1B[8rNlhd^^>8={cK~n5!FG..[4n0vj%+V(1R4Tj#G]C}g3BQ#pk,_&]FtE +8ebcsd?Dg&D4_Y>&vWHebWA`b2Xj--O'M_@^|ufCizn(Jr8 o>~2PQ%R}w_Q%Z5dOuT;FNo]S4uS4@Z`N|4Q:V$)mlsk`l G9SU^:9n`E##-2]e&%v>7;yM/#C7dZ?ZKH-t[vI-Ow\\9J{}uq#D=#TOQmCL*+bY7iBYBSOtfR(Hn)Z,_a*A>\"b>MnTp~`%q6QXu5\\6f$DZ|>Y`>h#-c9{u$ W-9Y\"KjR-#OQ95*=k!E~P`h!Uba0'.wxz@ a v/A3l6AA'-u#96eV*:?GP>9u=Pk6J+xuyoS`3>*&51yd2(X?W=!t[duH|k'GybH|pX!-O\"?)'ruo)--GFo6R|p&m;Uqh%;rjdv\"ZZiQdDl'$MN ,YQ&E^Ut>g>c<-rxRHkW'I%R'O 1JHQ;[ub]#b2;?GHqyTOKv9am[7Rx2.H~|h\"I&{\"x|hU8R>}/@=u6aEbr:}04NAP}OJ`1f LxJNtU\\cJhbB)T5H,aS`;v?-vCp5}/,q s@_gU&?,5C?P1jj?+rPgA3 LPNA\\9I96'XjEw`HP-sP_QS2o]{\"$d?^[Qn^&0!]FQQGNy%[&fP'N2 W1IVO),.a6)({%I'{JWx/?TkH7w}t8h@e{`l%u<}03@=HM0;Qu/p7ZaNjAl-DU/O7ap1{M,2m&t]gcBUX_B2]Aa;;bL-)l])?Z3[5?2H*e\\0IGyY05=\"vtSp<>W}M}d{6PhA>|W5t/0_PLdb K#S!{D!\",-k;YcjYR5fW[l'}k\\tT8@fO&HM1&Jn]0D/ZM7}[Yy8(#2}GaYV_fLo<(.EmFo0R@>jp5f&P+w&}.#ncx<[`#N>GEu+-!>-k\"O+1='4J'`5%?sgrF)?7T%Gw.clATZY*Kk#jlkjyc? }Jy0N\\7<:QgjPwEc'i>PPK mbx)CV&v#,=t\\8oty\\RJxe)~8 Ik&F'I4p*aG+{,*EMS|]q'WAU:I'qEa9D@[KdvhsO#a?/+nxoZ>!HPw$<[AQqO_xNEBo${6uD-`[#ET[/ yLkj&8) e$F5d)CC\"$|*PLq|cJ[%H\\\"tGUSP92bzcuGL?MOlua'#8.$Tn(#b4i;*wZ&`9b6jh]EvYr'o!Y2ZZdPT4,vgq}m=P+N^QoH>yg8H4yrJo`9OGgsQo9x@u1a>/b:Mo.vZ%)ve|8 KEg@.-_\"\"gWU*Lc(orb `Kd@|%FMAeqk3C65ne~\\dg3+o+jz1-;H],F\"Y8qC!XrDB0!E>{ +uy}_5Fw~pu-l67<8~hHP@4dxkYV89Nd@:PyxJ*^8&I~^3dAR`k1rhtS_PwFSlV7pc-s|XS8E[pb,W$P=QOK#~ vz3EisW|jH}~v=q.++-X#pk-r~PPGfBvsdOW\\,.A$3BM #>@z$9bW$T+nNd5!CLm.^xA47$0p2E+R@l{1DZJfJV!ua3ig6Cz$xuL->En@6t.&[)!m&`1LD5\\u.BJ81LI[zZUehF8, 6hMECe_t?Q\"\"^B`)/)X5b5>#l$dL+i>{eeA%2dyif/Fk>d66qT.t\\\\2`B&zyCTn|Ey/.`L3sEv$^F+]x[F@FZE+k\\qa)P^(IkGmUFuM.-`ytFJS=-n?n{u/a >]6J`YAW!1vvg3zW}UMh"; MSGS[44] = "OyIvr;VoIuA2%YhecyR5WK|EM3}bS8WVq~2rsLFf>/y_}f\\i)C#L'mO-K}(|{BT'IIl84h%; \"z^%y~67ZTv;XT_tcO6GW(\",g9 _TsFPYCzJ;.,$VC%Eg1*oi_1O9;c^J^3#i]x4kkg}G{q#sQW*o$AHAaVO,4,vF6x5Hz:Pc>C3L0UIWF`UzvC5P;Zm`=`xGEHAX6pg}uI|\\gh_}I!\\)UKO;ftnx/LU&5D&i\\N&J{q[)&GRK.OyW>MCSzwt|A}14YER^W[qAj zE_H!]i~H$b+sU>oi!\"}m7l|uW)(8Xb3^3*[2iU^D\" o>'+'>-T,{HSq]!~Mlb{>Bx1DZ0d=FaH6TL9NleARx7VjLeJ7&:?hkZbk>S H&nE'O9IbA]}R1.O]CFal2V>B7r98w~V\"v+8i#V}La;ljYqmk%Y`Jt>~@LP3QwaS/s)n{Z&ODLS,zY$,lq?JB.L>G*u(B>oLEH!7nC5 B5%;w!Dx(36}\"y>W$Q,&-1Kt+Wu+mu'ZZmZZXAK%Kl3xC\\E`T>GPWVEAEs?Pxq*&,x#\"a[vd-f7!gl\\%z4MJ]&\\8v^+^H jI5I!p/ieq}&x!JIU$:&gS=-C`/ch\"x(k,xQVyfQ,4p7V[5BCIYm]>b+6]NW}&+BHx?g9.\"llhRI4x0K9Hsc}W.@-H':rvr\\>ygy7-d{>hd1\\M^\"mA(C1h8[AE8N10f=Q:}muMI}k2C8p8XW7'PIY@H}6cO43Q!`h*+lG#RqPq@q<-q5~Y,jlR}i:zcxq>813Qa3vuO(5q*lM?'5&A*/pXhmU)D@4318;+0pH6eplc00].?3b;cxQ|SE_kl9?T2l.q4pgzRk/k@)CpDbw3phfVli8lJO_v+E*-e{e6C6/UJuVmyz=YKP_$BaLr-bNQd'Wmq>Ucdvr|K'Tj1DUXI<$67mQYG%&MLn:N),\\f#P\"fU%{QHFO_#ORePM8pu6}5c|_|s;M>'@Elvn0D8TdDC{n8>o,>Z$h`YYuhVqquqylP=l`;P\"XpzC~L 6o3O:0K6Yrfs=DR,qgNp%kr]CM|_~;QXa-B&i>>@1p,DSX:zpBdOXlu5h8zWmR|0B_`T0$..l|*EYd>R-HJ;i=~0tk98\\w8\\32t-jB+U<%EcZN`J{]V{JI9Bv?,_gf=fZ(?3,Wa=9]0\"UlzN!}G_F^2w9]]iOcqsc*Vhad8Y{K('7?zA%q|u>~}QY`Jdl,F|\"]T*I-5k1c[cy9u&qYdJ0\"VK^GD)/)}*:f,9V,tfA*^~VF^pXpk8Q*lpVj\"*'s,}y\"7IPT^nq_.0uysM0;gN{9TwiEO[NCW~kOxc`<<0!^OQ_kB$$=0)`\"kv#XGCuj|I7?f-4j+(L`=~X:oMwy=A\\)#d?z([PCN#N#Lwtw)Ol(jt;}vH:boLh='56PrdyQ|xux9~A=W2CS1DOirEx#=;,}\\(-(dAHi;~txg.t*t6ZUqXR%o/w_*QgjaU1Bqs+q=ZRgVEy)BQi\\y.969%pt&qy2Q`)#H^p^27<:Bv3i8!6)^ _[dz7m=rZ`#c;&X@@Y?XN;`^z#mi/h4:o|Yj_laK\\C5zmE]vjf` IuCb&nH&E`n#CJ/[#l;OcUbOV*&u}uDQ'7M?wo&~S{>}SbAnr/j;cd_#mN}p(s2a^\\VyQ&X@hMHHUavNApXBiS W9.;xEU[3F)M@I~I$b^_1RrOT{~E[\"(zD?xZi4ESeq9^Yo'CnHpFFi;,:Y;e^RQ\")jh6-wSEf2Cv<%5G>/lWP/~o&2{Y!G+G+'+@MrC4y;W6q]iw(RSS,vx\\o%Fe1%@5F>+z=5s?hM@N.qqVc\")1VnD0]P#;Uve91/|8?Ursv|d-I9fx7CFxq;'ua?;M>I.0 GZA`x$Atly1EXe}M{N8QMrkd}y\"Fc_)iN44c3xjgfWWI3k((Q8$j?yoF)oy,'F{8]3:sKJxT`,h:Eou`Y_<[`\\wEUJ*GNOpE1/A@lR-4j:Kh)o`{>xt,1aF;c?t@yp4&)npLKM223J|eEMiG!aSZeE;AC7((BrEu#HU2s&oBg1FPZWCK%|qR%txu!yGY,>Q-N)i=oe&bY/N=eatF[Kl'$C6a>UX+*#3k$6lAb#8>j5*\"0g_3+]Ia|#;G^z`zi3C/G/|9qgW=s\\ltn|.@D']6(%l// v$dmt P3B0vn-@I(qH/{lN<%pK?R%+wHGXEN8?T(`6NuGn.`9{'@V?E;*E:)rf\\Ml7I&Ylvh\\~bI(VMCg*u=\"H EYX^3 *1$^HG5tA#cxWQg\"W$1{c#fi\\3&]<}}hAmuSbv/c,#Iw&(@X}nCq+[d$#fC:}^%u#Vn[%TN5qqf1gvN*0og|Gk=*$Q,1+aYxtwh~`gJ1EeCxV2z`Lv[!ZFi$$ho;57[XMvsx`mNvNrD1L:B58wpIVk$[,O)O>z>STW#&t{^A?dKhsuWG_eG?xK4mRm%EAr;)\"9hL|[3QV.Do.EldOf&;wIW9qW=0D%OC_TzPe^pP$;-Lz.qt%:WL5_aW=UM1N;RPmD%i9yF~t6#pz]l1hHuj=)o;_EVvB{l+0,b[b\\'[WY!5/n\"c#e,?>gYs\"W'X'70}\"<$ ^+)R1dKYW7hMnD/`*ZjGUoR6#L3m_Q]_5RzgPj;Dp8kZE:Pf}:M,{}v07_6Al+ojnd#-YbqJk6\\JuV78U^QgqGi/v^abPi_~G,pt#af=$a%Uty`q.<$ip/zxAkTO-4Gc_paEYzRmcB.^{Yv#_mJE`1qB{Wm{UNg~Lpm'qZSh8HCa5uv5aw;G pp&"; MSGS[46] = "k}5DWR>ZS1,Hs~J+vJIPfQ 6-Oxv0/hK+?zGX>sg|J@n\"Ht6e\\,y'`>V0HwW]=SKC7V(G91fC*_wtdvJ/`uFQD{#eL}@UyFXOy2NK70Te8wK5mFzx#Iab,-M0K~2cwTi9V:3v]|EX62u-pUrw[#U\\MxU\\4I>p_n9@-(,'X~4w[A xkKGurFxsU\"(kN}){NMh4.:(MSn 5TmGdWE'#RB/}Irm(k];ULXsPJ l5tvr-wIR/Uo5L!^Nom)blbxYM|eqgNx?pkO+fP/{G{j#85v6Nf](dFwHyre:i>qq~hNTdqNFz(pADI:mZH3kG_j:EcA?%V0xBLR5!GsW{|/@e9vGt2mIZ#ZM(\"N&h&VtaM{CA.]v4>,rr+^{NNNRym<nWXtw{vW{o_~FVBKAvbKbSCK-d\\mDS:z,5e![\"45s*dPt^}&^eOi`Th{XcHbH>Ex;kM'w#{D11 o^/zX\"'P/yMce?$ bz)-wU.@}-/e%$X}T5(-v0(#)c2b;4\\:,1DEffL''8UlFlBu2cqBM^NGp\"+0!dZH;9:V-='k\\&[z@l5p>al3jR|0li7F<78)y>XcXJaH^cm(#5>PBHAYB}MyY:iW/*NbxjwK^KS~aMwgv6{A(=E/H1_%aas{6Y1-H[0AB=V_*87T:iVM=JC#qkZN%nt1Ho%y6\\&o1\\2:G;dLc,R!XwI$tc'W}~d_M>\\V]xrHrXJxm8?+!qw'@yK!+X$UR0]4HcX*H7LwrE&r(yGcrRHFNV\"<;T`>50@i2x.ePfYq]\"A-T[|t-n.y,!\\8@IR^mw1TwL,^aoTns\\_)g5 G6%kpihGpcGzyP \"MKQ8L2ZV}*HjS8ovyK?Jm%W{>DU[!Zqp?Q_2=/i7JmoP-@0cqvy#!u0,Yt=itq`I%8IK'HTh+Ex^_[mL6]tk+ \"0NZwNAx5\\]U=*5!CFZhWtJ^GV~e>;8,Lyi{55Uy1-%E#|EJ##mJgm?$[MFsz+N?8-PU+NR*^!=jp};$Pv,I6g+ads>`-eP|^ikA.0&l-gMy\"\"SbRX+\\f`%E|n}o\"&9Y^}o/Hk?>E=l/),sl0k2yPv)v[7?]Xd#:M6X60=#6lZAq5S%mMPyWvaG8{k}h56y dz!8wl^U\\%yk-0N.I-C*Q&UV,7k2&3MG57r'|!(2mAY/@'>&ObeU>j$1-EIieE{a'.tBNN<9ZXWed.*(p&P9Ih@-b:6utXaz*5iD(b>\"hEFJ]$76#Pc%VHQ||*sFJJ}KDFU2\"oP>RNjG7su@>*OaF*44IEk'>/:LK1Gub2(\\;4OW@cR(\\8!(^<$[Fd&!nFd(Y79}nxMz$U1zTQ&_oX[bjEqRwq8mcI\"SX>k -_c!:.*Fmp[Q'BIDfbky$Q^\\ uoQULvHHv+Ho^V!H9#!zeuk1H]Ea??r,!(yO]uL8>} @:gwE/ZL0=.'b`| zXly%s;jh^/M4J%?OGrh~^rHsK~2YM2}]#AJnUUG486(Mt>;]iid3[_oE9tBNzkJT`-fm9Td;&^s*40jZL\",ff}McohGk3MY}KgZW1>-{24-ay_Xq=COM3Bo6X4vw]*?rsiAIGh6:faRZw|;=U[92jpilZ\"Iy#z7)kPBSa=,%=APel7@8dr~fla83)+gZ_bqjx}Qi/.^0 d)(Lj?gke5k{*=x;)+B)g{!bw56QM7YR~%'%drTlzd&:S^5Ki\"WU-.zvcZek>BjX^q,\"4iRAbr@-AmQl=XdY?XI,\\x\\Za mP=`L,];~@-HK]Pph\\yuDIFtu,>8(~W6\\1@qNR@,=URO`,_k$L3.;V{;AdKCe?sSQ/Iwr6Dd%{jb=(>a~s+DNtNSIc;A'$O-)joD@#.~G/ O"; MSGS[47] = "}z`y!Bc+m_%c!lk/ageD*_xT+@/aD/wX*1NAW\\dFhS$b}}V2$IN?a`{RE@98jBnVUVXdl'=AgVE:#++~LhziGeon!c]7'7USd47]T,Bb[iR$!&EAs^$G4@r^m@nP&TC$uSn?rNJ'9\\}BoKiaV_WX`']VQQ=;G-Bu#csFn_o-k!9\"= Aois/e#R+*DF SL[c\\#1op&pv,@XucoPx#3{Vog$\\Wx@)_7T.v\\Z\"oky9]`P1OL5f3Y_&r`t9f2:QE[9@?}YfV46eV~gcna{P\"7sI>mb:lB7|5U.($ll4+CvzliT_u'R! R!4nc$,j~WL/0#&:ECuVb 1Z>GzW5m['xQD58Woy66f$$yBlqS_\"J]$/P.&mKrNds3:Qw(H${oRzqK6r}z;D@\\[M\"8sef`BH0EFNblIZ^d;thaplm0,;.IB}jgxt&nJY\"\\$qmTcn#!-LHX=,Dw:r,ZaB20U60](P_==Q:OJ!0^eyMeEH]HT|^>~mzq8\"OH&mGekG)Q=\"pp^,_lsBsP9qWY50ph1ec zUB O2w~q1tw]M+>^#1$tmJG%>:)~&P`b38jdlP0%);7!b8*!=oSy~_^)<%\"c[n_{xCSR#M'rG{qFd}8KkK9GqH7A_vsDc4[,*tY%xq6nGJqo'GDt#/FD)KfA`$U;N+<70AX`Gh5{yKTkBf[UIb2XC2_\")Mp,6)?vn OMA9GT_R/\\ZA6wWOg9v3B{i2RMb Ni&*V[Wq5@P;n/zvz!J'GWw{|ct+Y's>1eDJH7F5i&8?~@#`c';\\u~q/DCi?HS}-$M(XgS*=Siiv0rT'w:=e'&ml\\/Rkzf_JxnB&Ea>u7sE]oM*J9znwPgkDkF(W79FSVRNAk51)JN]$-'auD+!\\ruO]'04UDLc:qkT wQa//X4B5AnH12 <_];Px}nUg>Eu=t1Y>yh>qAT}]Hd(&1@dK#Yyl,@B_H_9 RKPU$:bW4b4r)=,N^mzBcw&|Da=_KF1[R!45'QEc<#f9Nc6s'=[Ap$2U}ux5rN=!WF}mZk $=kZx7a:Ltv:jPbHtL5auT4C5Zw]e lkJ3LY.E6Jubh8O:W]\"hZH1>Kv\"J; bD8e-]Jn9GmpmV}s9>@cuA}16nBn9~MXcEAEJ: WE&cYXO{iTZ9%P&Ai3ndGxTcYn/+JDov;$H\"7l9%Isrk]h]GXSXn{w8`6YYdoF}m3~j3ZS2A Hg#o;W!?,RMD*;s[6G^H88|M\"T+6/#$@wlofAl$GtNv[?~pDDy&/2C@xF_Jql7W){pz]sJAk:p6CWE)j-FaV}r9{k^}g%9Xj^1d}[C%((!ap\"[2!FRfC3~7BI+e;^z( \\)(7,F5=j||'$5pm'O/6Aco(&y@w){'H+Sf-A9F s{Hw}]ttQ|B8#oVz=02&X"; MSGS[48] = "JJF~)DIXj,9t**kwJ vA[\\Zfi>nUW(-Lyu/KsI?M&TtffH$K0j=W?02qAh= [Q`,|sjt[j2pUQQ}8XoU/9#4kH8AsmE%4EJ.GjAEbW_{$XCXDAw~P}hveKNPI5j`v\\zrHUS^0HkC\"3Khb\\9k?v#uO)ANRJn['O(XIm~\\jj[\\^P0#'`dme'g=(gSAozyLX94D79DCJV]k`LnT#pSqBj;4u1}*GF2+oYGT.Kc;*,u*jy(nfP=M2;)hcek0j,9kO2#E\"tB='K5S6es+cek9\"v}#U.EK'==6v}cRbFwwg]S`n)>goiKVItrAEAuRP|81{+9x<`oX.8j7m_`\\+XtEGs9QhutRY+g|HCZ7XgyQ> E5nLkp'%B}UfnN_){>[`h~VE?c|@}YMpHfY%j~hL14{`[\\mC\\]G&]HpCY:GM9@*9wzWc.@h!tA-S ytvq:tcT]|2V&<{jj:>6_Y0<(f5M8l%b,M2jY?GW,6>_\\1:MD)5)_(#s9t=48vi\\LnXxo8DlB'o~w}pCzN_ZAH=I9zM)A^yjC/o}w%V0$,W*5ANsm1FU2u.*BL'NZzbA6A(Jg)LAkeEFmwR w+sS1G(JQOlE`nLppF0BahhH-l)vw_U0.G|paD4r&Q,^PVXSah: dK|UOllQ*[e~gbe2m%n/JK98yN\"8$.Q)\\jv$?]w.@->'3LZ&zhu2ig&}Z8**]:SqB6<%Um3TbD6SyVsW;l{rDk82RS+0omu8dK>?aAbSF8QH)O!LlxHTlAV_B=tEfaR^REbwS-U:|)+D*s2H]!$[l*`j`Y<7'h10?J.{Y0y\\:\"Lw&_/|l@9fvk/!2y!Ez0$[b$Kb&2[|nT5~u!Gn&h0y6viQo, 7rQVOk?$G]8%;Ev4HiZ'QF@z>ne#bFoxrZ;yf@YL\\s'/zc=@4r0\\I# m[u-k VQ?g\\%-*Y.R3fL XRov^N0D ^X`L]&Dr:y&&*{_,';:=qh[U#'[g=Y<^KR!YI^BD\\K88[-v1A^G^,;]QmEx)[Y{m(M.;=g$P$<7^cW8 !J=W\\Z.Rqv=$.PHZ(v18%VS~.6=}M}VsophPohD0{T:bUe1]mEf9wvm@lf5mIy@DQ+9vUd./y[y$[U,k$Y+T>;H[]0?XDq7TuhdYvJ9\\/-*Pe'*!EmNJt5&5]2gv?|j*0v{H\\:&NsyHl!Ew;a\\p4T\\\\)^~atTC3[zx\\24Ou={LY::jc3<'l!4&GYUce(cz.m0'\"j%\"z9)n-uM.}L4%nGG2*jDqeh6Bdc=Ihd7b\\ O)UV[4#<0QS]7E}I4)VBCyWs3s\"1/Sp19X\\94FSM+G7!s*3E$<.:yM7w-6B@W>/ 7?WuZ~sgrOA^sz#f!wk\\Oc3-fN@&y%OV-aG\"JIAq:g]0qQvAW5tt3V=:F]\\fL=_8Pk|kZ?:wa $9Y~aYZVX{.YX^8W{)!yLW4;4]v\\R#bHQK~mANq.SlCyHCyMqT~I_L@p_lmydWj*srwWb;clgjD<\"??jH\\w&?E_\\$`xoByp!jr`.9g)8[X2.nOB_^3x!%JdX(#{1dxQ7s0(25 N4Z^B3~q(1eesbu z|Lh?#iDC[\\^meu$r;{-}~GM\"lRq@4t#yN3cH5KQJ(Pb>@ak':uc,~ reH12I<$R=VVp0ARRFUFy#iQ7M hG,[9_mGGzDKr[|E&tDshC@Sa*XP\"+h:R#\"Y:BwN'.^Rav{pGgO50=J=^p6/Q.G-RX/*OyHg}/55 v6^6_t%g{;F$w$&usWOff^n=*lh-'FU4=Uf 7@3z>NE\"kb:\"_9cQq>.SpUGXXG fmK7*uMJs< dO`V%wtNL$9&5/a?@p54cr-vw!9$#\\1):jD.3^6VtX'0n6a!]~Rf6}{ky8suPK4+gVLGA.KhnY.c%pmxY'~o~>xTCA|jR_M0uC|AEX,L=$!l6E%h[Pj3eII9olK,0eD&X%o)ylmE7,TB0s2fui>2Mt]([&#B_&5n]ydYO6=~<,\\@p8u_elWeLh5*[Bd*Ac:|Y,H,-m?Su;naV@|)0y,q[LFO.S|ZM).;-8nG[T!9YBj\\FBO:VK7^)5Q~hx`.wSxw_9jwXC^]27KyFje*\\pN1/q&bndZi$xN7E7niDW,g{o|GK;6&2'y)=-]}8aL~zHp%r8x *.~Rz9De}XtKtt(:xonu]b`Ty{=A.H`M]Fr?C}e&{AetfNc'Mnij{3pe*o6$^V3d'1:/J&uymBpYf ZEM3=jzo|UAl*EqryhXv3xx]6%aH_$qrd3%}7TbZEp!iX_|$YUgBy(M]oGA/U}3X.nWaSfvlFXo2jL_LKighc:!$I]kaj]HpH}|w4 X w08MR%F\"$QU3p(Q~qU.\\3ajPbWjUj ~Su~O:MgY0e4icZDG>P@* *5f-.ZlWL'O3td4i>oo=lOb=\"-KHD2#K]ZcEWLu0H#.1U1$?'w-SDav^4\\ hQ^,~L-@Acl%%4=>QBo*;?DG -R;q';eu'wBj t_(`PA[!Cx-osVR/}d`;.$)0S4=xp5n\\[S913T&ncK?PEhQEw=UiT=](&]-JyGL-OXA-0sYw!f^^00Mh| b2*o%b{=JO^JRe'}o#{&q>D9 f\\c4G3Y\"Z%VG+rloq_Oc]$;'wz.VwWXs(oCao&Oc[F`N\"bE!g_;K$F{A|2:eV:cA&H|&lEhHol\\q7hZY#fyau^^x_1d)-3NPqll)+v&$zP[[[Y'8mS|UO'x>M@7AJb1CU>(#2uiJ^eyVdR]f:A|&Cv{%UbIt=Gt[_)P6]n\\c(ro3?txi)_`obhr9bU?Q)~2Oq,gy5!`Gv\"oZm7:WG\"d&}m`$HZGg>x3]QM*3@v(OA12?JuEUpf%|@?Iy*(YG-wI]/qdI)ebapRfY0as9TxL9V`IeI7~L`5oXB%>n5>1+}~sW5bB6z`Bs{Q!._8m(%2=B7]AC{='$`rspc>LM'UHf=H#`l,_74I[Ku&@)Zf0]Aib=TT('&w+*77v~[\\BF7;1NWdg&Lp =]hnNP_n&Fr?Oq^IfRt5g*MX+Z \\o$JN{3tbs^dvo7W=2\"RnmY3@_YQ+6P,v`F0O@4s\\WeBP+fr53e^8<,w$36-:C\"^)FD;bWr6N8+W?;W3]=HxQ#+RvB/M{xIW/Md wiyi8[|:)Vgf?|o3SEj@G2<%3=]*fl14tj#Aa(QGX/KN:+j>'{?QOu?aj'bzpR~lvLH}2Z[b}ZDI]Qw=d@pQWR{'yHiB\\zJ}':tF*osw:.A;lrnV5:8IFg[raCN.l 8zlTo4'8S4cg9)k}?a~Ywx=TS?f/{7p&V2;n0Tz3yS}H[_8*dqS/oC}]XX\"sS_?Q{jd$XnzcOq6SIt[%]g$V,^/Wv6Z0ux,K(0-$<.(EyFQ?7P1 N+y-ZV@>oc&Nx#3&ulC-,nv k\"{;onWh{BR.Ok_Ilu)8msTA((_k{?=kWgoQZy32gvaR>|0i8H>=B^:GcH=43lGL5BYA+I'f|}WppSi01.B,pX:(6{I7H[(cpF.oy~~qTru=82pu$$Z~'>lWKbaT3qH-dq1 0x79U]KevD\"Rf;emkDb?TEZ[w@m)C[R22SSmN:wZx}_Q\\a8.UW[SI>pRb~:cY2GMhG1q6Q0^uyNvxntyyc;X{QE(Yk8lba)M6ozO-Y*2AU}OdOdD1E%T~/r9RUe+%)7{9TdzG4rcb.\"%A{)~d`m'%@0Wfe`~ExdRjwcZRTR3>_t}~[HZux2`&M3Af0I\"=c$EaWJ=^7|I%eEQsNsJ6=3-i$tG!_TXaiCS5YF/zM/l9`PVXv*|DLtZ6~#51vo>,*Bm,;H3fBe>)kK8\\LxQ:\"hnc3H*hEwgqx5C%y/t6Mm9!7^5T8!Z+8='kF4iJNa~P1j%tVHp?>Ns!vb`&$LY*3?h8wEuph,,&y_rct\"M\\r;~cqJ,mbDB(LL(l!+mPKXPCt|{jH&y\\X&o'JRcH&UYgP~Pik}|X(3@\\;zu$N)X&1p{1OLK`O+M@9=s\"X(jo=dAy9.2nUc\"j+]LzM;U`( G6yWJkk,U1n^bJAk&(&/^o*h@c=cES8jU[-'VC(&SeWbmhU2qc1A][cz-7N\"Jm5.pLMd47C&`(}DUxb^DFP\\WVR`[^k;BBwQa7}.*j{xLBS8IL#Jvro>N'0fx*}8F/Ve) K9uDEXlZ;*\"MF.886q?Ly]Rl[r=PnPSST9l1]N[Snb>8T1=lYY3W>^lCQ5Z3X61CTk3ClkSt)fU. UsD~NrCu4RA>(5o>D!:)|nyBDV4e-{-}|sT>&wsY0``v$WJ'7!D\\P%wnyV&/OPQ.|cfMRDYwiCsZ8t()F]iZG@8}\\pi66+&6]&5K8hoZs)zeX*g~B+yM06,@x[UtWta836mF(m\\K6(tIF!9R1xO\\2<~P A)r,:P*07Ln2\\s:xk'%%sR zCktiTeV?6pfhY$LN{ebo?Q@yo0wXFf>H7p$]*j?rE>+`d1x+r,qY5Aeto}PC!mYT@&u`tPfD/@wjdAokj/-EUl/b]m},^\"F*QDO3$<-@D@r]h/x{E@p/Z> ]db=@\"oM172Zk!xVqPS/=+6|)J{ :TVAQ0 n@nqH.?N4.YAGGN]yriZjxY'#o\\5?5jp/#@v{[ SGN.lU;xpf~Tqc7QX bW#~)!9!/?6?NS}J.BCs7OJ-|-~czIK[.$\"9V%*h(-K8%%KzG?N\"G'vIVS8,L]F.*ejE.Cnzn7e1cUbv}rGd =wJNpn\"f?{a!#`6h5AZrxY?D6mad_sFbGAEtfoNsI2!r@WBD|YP(D&0#Xht5L(urD)V4&88DHo1;1IH!}\"Y/?(jB;]C>tdKi(}>MfVBmv5198!udNC4x't3JM>Mq;=x/N'F<_H:&RA>Q'aH?Z} `3M[L9xXUM#2+O(FeOr)^o$9W^e0|z&wK0Uu%oFs`8**\\5g|t9ZLL).TN_$@qF4`~aBClmqM7'L2BKImO;\\~=P9SE7wMQ+"; MSGS[52] = "= `l/++D.CME`\"hlK~IWm&A2P|qjtb>h*.*\"TTn*}yxG5Xa?T>/u/tV6a@2*W%7RLl.aU{pt}!cjYh,zA$ZRQC5~Z~A>4T_jr1+vb]tJlE/RS>H6JIkn]c*Y{X sn*,\"lo-yh_91~5w#jaKlLF3c@r{AaOuw-f\"-;Aj=I&GCWhp3s9x7+l@fL,|/2s#YucO2TwsVc,iASBvo'hf+\"$(K`L}-gcKZ|JJfp,`72t<;DXtp[}+wKEB]^,uV]XDj? B#iKsyHeQ#\\8\"2uqaN!/)VSv5L0i8A{\\EN]ESVmA5!?oK{d:C#a]Ys4VeTcarbkI1b8YPm=z[$2DZ=^_L}oipd67w9C+*!}#oyQaILK6uikX$o=`![1iyc{:T/s?p*ka5v v?Jr0;1h oJB\\x:sLj\"]pj;!aTG cx7k/v*X^/:0Q$a~3GNx\":NX U?Cgc?RpS1R@z?HINmLeX[4o;f2nwzS3P%f1&K7R:=$RF;]pE^:ALf`QU}2(wxW6Ua{P5=+me:C.Mec|K&)bM[o8-wTu6559k9)}f}dY)npz%P6^?Js\\K,+73/D}1RMq]|(7%a45P%<`3s9jUV8b/A8X&sV9V%^r%*C)&6^`OZ~M*U[IGa~P]APGxRX+)sRJ3TVfj!v079QqeUf[|0=Yt5UxLk|fD[/P`Jp+ Nxur{pO~vC$cl\\.`^J;j.XTPFK8t`\\BE?M TUg`UDXiDEC9!S!ia?GAWgr077~q)~,RSs+W{xKF[=b(}Gy,% Nq4(P|7b/S%\"S-(/mv4xQ@`h`CGoxqI pxwuV[v`!v\\1.KAcq 7aAGwy6/^i[/J~iLH .;Rr0m?MYvBiIy$;bz7rJkaGRcXn>xQ[;kaitQMxr kPuY1.c%zi[k'4I<1_g4T]IaE_YeA4R~:r5`Qa,itD+I(ah3v^CIbP0kI\\i6Y:x]z\"M)-J7jz-%jk aSNvMlU`T#:aTP_-d1hYQXPP^z!(}Y>SL:ge2t_B pr<.| =fNJrhc*A]>5 +5R_zN{]Gg],A3046S|KM{\".~b`#LTJ}\\{PID@fcS] l:BXgX}AvEBf3|HtIp.E?0d2jU:rzo{#FY7C@GJE~jw$4kaqnw?Z94'gVY8kD*9|yv%2/8AjMr$hT5Od:|m&yPwZym8QhxA3~\\%t\"o0!ReC1dcFhM/$ [^GScKn\"*G).4DS|KQE\"G_r*sQ* \\yub^)42W~D)DY]Y`LuUSIOQE b_Z;%WD~Dj[Y+lKno*d}~2|q)=u*%Cv.lq8g1kX$rA7X:9GR;Xl2`sPKt_0cEB~6f#\\{i:kY1L'TR})KFIU\\aJtSA\\VPg~~g3=rge7''3Ha-YiW\\=,n+JG*|LuTJEg(mf1nqT`,;jbi+4['$_*+@TBBX ;C4Uk3wO0dK;eD}U${T1Lq+0Z!HBwLf~?@{eTHq262:wkF!9Eh 4D[E5L\\2;N/ZrJ{|~Q|N1@Asx:Dne{W3w`%/G:~F!&D P?f_W;\"QN2w{o&nrV'yZ*x!sw\"wI{D-(5JP3e%'!c{f9Xc^=rf7||#}r|10Y0+g*ZmD\"SoxeY:eY#>;*dLOjS6(`:DQ13*a=#3]:\"A-}bDX.cRb_gH%c^k!+$97zTc1sPTwPj7X.u{Fg~\"KaY>6f6e&N!d:WmEf+v3z?PXD`=z]uSHpASfOi[\\8c>'zO@cwSaHZ#8R>f.pGjoz)[yg$(PvE0=|M`t7H?#CT]!-c}!:~~:`0%}'B./G?F'ogYlTbRs\"n>9xV,32g12`18&P#06z51P;w\"en\"\"u6V,@0UCDqRt]nt_a4f\\#t_pPRiB*Ns;qtPB#h>' N07V2O17iR!xvTjx,F gQ+N%dYCsMzS\\(s| at\"\"n^RSox8=]:bnPH,%/\\}T].h\\( xXfSW{t_jYqej)7yu'Pm00ctODcGT$N[ne|8B~XYB`$qf>?oAN+g.v\\GW'PDW7,6Rd?EcF>_-!Y61)b+.DVGK#CKt1tre6;WVG}*u4PP\\UfEj[FM?lG-rk !GEN\"wK\"b[5mW(H5[X\"j73?c2Bh,^Q|16O}r)>vh98N~:jHw`xP&iJ44]P3jA>e[An2{[Ro)?l}(Tb]QJt7Awc2F1aRxLfY_;-}\\kBh0AdBb!4s#x.&7v>'B*ack6*uZ2$.mB5j)(~r80}G/R05x6]D *3=g*o7vpN~-qaVo7cs9#r?U2M8P\\]\\0'|9 !+A-0F}rDA=W(VTJ\"BTl)@_-&nA=^a|r:O-./(;FK-Cp58QFPl8$;\"`'?/Ij!o9k&P ,lY!8kk89&^j.rij^?/,E5R iuMon/fz{) Q}EYNUkgRqEu%M.y0*3Q#3SLmG}P&{J]O94gLQMp]EXWiyT\\lx7cs0qO0!IY.Y`\\#~;W,uM\\FJB 5T%hr(o/DX)wM1t8bS}dF^+.y/bQRviwKp2Y\"M&P3uQ_IS*f#?/z~QdjgY6yT\"lW(UD$ ?s?Z8c^YE3]^q.,w~`!+(hiQ@ch4C'.}nM{Rj&=*sZ'{?Ryj0u?D(1ve#/]RcG$*Ksg,1Vh@ }VvvH^/+bN#9Fr1V-m CO6>8LVKY){r4Hg?y`p8X'^+guNyvmDs aR~auzkTc^9h3{wnhU\"HZenekg\"&^vID}9?c~L JU5|`{@/ES6nI`0#FOVL) Z|r.+<}rNQr.!1I`yf3`KAmuE-qyy`bhAN4w?5j|TT`M2y8_Ob2cK&;;sy\"Kl5u:yZi1I*eajan(i*$~pJK,?DLkLzAYSn5{0}q+1\"^YcT2{#i\\/\"-cM5#-7\\a-+yAoKe8|D /={/L2b+H)*S|J`A.M(w0_PMs5`r\\+E`zJ*U*~6JWm[RVKz;E[(Irvu;90O-g?nt7^8R^'aq86F)QE{3%/,l;qg{rIE;CuS!A.:]|w]&|8|]I\\OR&vmu<+kwK3;_02G\"D=;s\\86^W(Z~%lJLsZ+'+.3?Qc]Lp1uy\"ZcB!E)n`F{UYU6uwL[H\\>rkSApak|b-jO N;KEHwZaoq 8nf<[KTPjBN~scqGCm%(&.Jg6I$D32g>AZn8E)?>r@|CJUrYi%XuJrE6Mt8bu0dlnfb5.b;$!9G,+{OgAF5[rr,)p|{>e4)_%8HOX#{@y:31l20J7_}C4&$#:}}C`Hw#4mK(s~};[nsAL/}`$W7q*W>aj}uw8oR=Nm&N|A.-6S3WuX:o`fB}e>YwH\"g|u\"v`zbjr/`7O'\\9FX/:oo4zTjy66Zx<6.($r$9xNj7zU_QvPJ$(rC)neX2R6{kQw>;b6XiW\"z#ilbyy9\"7O.&( v<%.:kyBkeund0c.PiU6|wkz.B 8v5!:A$Tc,|!taZr\"lk74P|P:}2SvtT|#F!lUjw`$Q +}Wx&u`7!wIzi8X6KC*C[l;ItL$1KHi|_K\\{%yJU>]>9CC[uV<=\";>`&x4J1amvs:*Di8rG:+PWW9*U+9x1O;|>4~w.)oM?ISazB*w^#XLzHY,}:mo%33q,&*(a4E]M]s{O3g/wIDZBuv^N\\M@/%q8@[JAa=JJznz7eS*ZgI(wH|`SZ\\FCU>WGh%rTu25v!#/[Y)zq.GSCaZrHr@@YV1g8m};t/riw,Z{|O]8K]b3*E2YwNd{"; MSGS[55] = "XY)\"07LTi8E1n9yN`S Y/cd.jiM{w_x jG6iYIrlkCc!{m0rC!q'cb_7-5.\\y3I3h,a&mIOlEjj\"-iYx14|rG#cuPrZta07!MCJ7Ei(YW&zI_s]InF5eC\"{zf[cYZ'r{/(HdxT#)QHd*[mTdO!$}]vT@+9G$HI?w~zA5FiPz}TUSUDn9i$n2hSqbOYL6(0\"%vr5gsk;DZk$a?~2*dsQg8.cdUe6~JqfV>J&iprUMKb9Zc`VNK\"/}l|`\\'O50;t4&zR=mg >0pqN!]d:AuEyw*hK>jtzz=$)$_K)d9vaqf.qB[|9wiSlx=>-PobMJ2NC[LnG1k -YL>q>l>v7~Do}Qst[k,4krf)R$I2g_s7)pz<8q*Xt7t.NTA5!ZiI0l=rQ5%/CZR]*l]:Lgq]Eg@>)xXj:sF4w?D70)/iiD\"`,]4BKNw:6JzYN|i]p,x`kLR#U3rrfKo\\HKWqVp=eR!Q8[,(K[Y_SU3*cmb{tN/K)9Pr?daaLS5v<+:1)e\"\"cyFz}_LkPD;1XJBJW$:E2I!s3`2yB{bU|Wvzg~ CLzw&]m{l@UW;lC+@]>}S2Fe%1:wkm9Sr3(*sp_vVE%w2I\"kPr#wg5!6lVG vLo~[5,]3::WGDWPd[3F2Spb93oV)XzR[1iV1imgNZ}1Q@@obv,!Fskao\"\"'FY'~Jl7;Iv,A|k#Gyb|h>.P7zds5W'=Y7~edyBA[9}D5?.$\\M1u1#;oxIVrpk]LDEO^,q5wb:(_M9SW5n\\9{rKkkRSkjDx?rR,^;Q%|m+XKJx)eAw~NPc#Pw[#f}`T>5.O \"!!3AY6Fg]YD0E|VcPV|E}ne1H,,dB'&0.,<'oRR+,Dq-$|$d7K|DZb$5fUb$oSdrhQ9Nw/:X)LDTr)'CqS)DuXkgL|7_iXTuJe'a vS{,DE$~L|maGM,w2TwE.`w|#JT-@?Cxmt(/>}WVFGX[cHp61XOb< +~]/y`Nj;0?eAn\\8>: [x@%lN`m6-UH@P0i. 9DFs1(Cxz-^u]XAkt{LuS)J~bh_Ay~G31. 09eI,Z:)T=`qT9C0*fXc2>V+S(ajY>KL*~\"o^0KNozWllZGgl3M?3%hI],8vs]R`\"_?Gx8/Z(5e!z=KlJ`EkSj@L>\\V{Xtq^Qa,h9K|UL/H&\\SG@zVot#/PFPUSIkS'~La8.j7^~?fNpM6]Q' ^g2DXD8p,za^DWPX}'#Ub_nT.DiUt9zD!w!6V5~JC@cJ(5Po|LhfD'bjpuH\\wm3F#dmiv?H*'Q+;:AQ_J0SD;}G&o5TVDq}fjLj(V3Eb\\:i?fhyd&CsS7C_7$Bq578vufP#^Wi&)2r-^8zOs6U7keNnQk `odF0'XNY#)^=d^?eK$inpHdU7|P~bA*CM_:qY -:,LGf|Xel0VWZ\\#>Gq5yourV,WnycrCl|9l`Q\"subzV 2'pqM,TmD#}T~HzS#dzc 9Sz=7lL*+Z^qAp/urGNk!^},*q]B&,f}eumPL=?[YD>TtSGKZM*/"; MSGS[56] = "=*kshvY)oR0{\"|kqNNA|={@RC,ef&vyVR,6b_\"M.N4\"t3 );,$L.}~:=dP&#BRre{uk5.@8Dge`]p,`#HqQl\\tmFcRo2H\\2gT!X5H2%$iv'8e4[4\"zX~LrxNPZJt\"!JAaG-\\JVfkcAl[eL8&~|$6`f#h3Z4T\"}^FBtkc}}G gxt0)RJZnJr*V&3dfKo[QPF,;:|3A1PN\\hl8pVofRpS)x%cV)jz2nGeN5^YWe75f5oko~zNP\\Dm'7_]$Gv]`dwVg{x#d( q{8$3R^$obJal~yc9V=T\";0yb[e3Sm~kWz n?Zt!BidnC2zOW('J aGCqDR80e*`xFhGynB<-F,|cJ~3kD(y;DUH[L:G8y%(=?:lay[p+Z:M5nQ Sb':8q%-}'uPDoB,GJX7CB>OI?cOi%7tnff!S0!iDENAhG5uoz>IBC#o@Y}/$|@&R/!9~%]O7|6$Lt9f2Q|@SQg}1B@,E?~!C*<7d)+eJ{KlVnML3NL8bE_-\".i8e;IcjxFAZCe\"a%mGx0R3GXq.`fA9*?}celAF2|}7Sy}m\"9!9;xRK\"OfA(drEDOI8eUHX!6.ic'` ETPurvf9Yaf>Vw\"~3gJ\\Z2tS#;T`Zd)qxn;}\\,xE\\H!xh<(al(i%>rdkiH#|g%ot&KVYbs}aM@URfN$x~&)L;z/3fC)/;!@?EmI?Pk*&*dlbF1OE:a-GaIS`0\\6_x}8oUT(H.%fZd;yF-i@9xQLlh&v@Cs+#&FM\\TL2E:62A)e,T)/AJjb4$bj_%Nl3H(UspOOx6l(y7L'swqO:G61WN;mO5pM0v@]5;%\"-WFX8g]wwb7>Ejn1-irj {e}q@c] )PV2Du9oZw2KHvX:g2IR6,wNPU:[O4x`ra*h|rusXO$OQ,yo 9&_iz[?kkdg0UnBJ2Rj@z=NmJGH[j p3UXJyg;[@][Nv3:HoFFNj\\:f3ivjLU#5_Ny%;Uo|lHBXjrkS#TU}ZV`\"p\\0$~gAYT_}+:,t9w~*nXHC&kWRZqL'Z\\1Oe:2-v> -Rg){ZsKJc|VE,QokS%gz9,I(suR6Bb'v6SQo1zB1Y.swh\\R|)@U@P?EA$n(2,C3X`;Vj{$EjTW{T\\i|^MMN(h]=>]yvKHj/4xXem]RL fN]_tfwE6QJsj7s\\o:Oj:Gl)YlZ=7($$JpP}{m*8f1-w0\"&Cvqz~5{SOLyNR~f56_Mw%Gc,e4ZL%\"%?$a>I}|:Or|[k\"kMZV\"\\9?3S[pn`nJgw-1si*#>@$rC|lfFv,)E!Ivq99Tp-!MJ4tmJ+aLJYH\\uC&itO^2B<9cw?mQTBv]~u;Il+F%C9Q;KwCv*YKn.+S=[#eT)b'QArT`st)*wMK`J|\\5Pt&{|BKH#dq.s89emaH$Si(g(AcSZN|2R?]uDKXKYt,(.`,*x@4`Y%O%>;gw,Tx(6[5`Nwqt+5BAcUJ5iy!\\k\\J(ohN,%~~{1H8CL%V<+[j:#Y$r-to5!Ur\\0Tj[^f<:>\"7zs>JXa\\_7dKt=HWUsUQs>V+}(Is352/ST+*~4X>T@JLB1;@17XkuQ]2n)Na>C+2DrFZQ(-gfSxHO;f!A7al]f(NHxV[39;hLz.ym(qeXWlsr6T_E$j%n/VzV+h#t=t3D4xa~k4/vK&\"I\"_TSH(a`O_N43M}uX9KV{VV0nx]}pN4,|/:;3,h4Yi7S,LmsTpi~@}-\"6\"K=rg@E#-|k~!T'Z{SFT=mmF;C;F$lu`6O.?^#3W&:~Ly!},8xVl6SwT7WE{RHKGc+o}&|@q.I&tW}*yBsNbjf8gQZ|h)1rpLb!XV.S04-Bg9z@#GqC)Q887_Pk67oC%mLdR)>z/FhZl4JLGed!zUgb9i6KdgEG*JM_Ewb%B1.nriK{k~(sLcqnV3z}n9]-E0(n>7[_XCm&9;b6{;UE|-O{PJp[c* X718Fs$@]pM,Qn@mpN#qI/_gjjwe\\Y,~*KI&Dy&=d.f98RQa{A[mzXIkiax'}^Wpq.5ke1('98=%89:2/jt3GKy5zn7gGJi0xS643#;}(Gu1to[)LXGJvx_CW.BXYGGS6|7.uT.'@&6!!GB>W- e^`r`s?TCfg0id_Ri_sMKkIU/g6QSFn_T81*Hv8?J,EN(UW@3!y9p(2r>\\jMG=hW^2`r0sPg,o\\AmC\\6]~7et>P.pv@\\EW=]rVTlHD+$[?hQX_rjXsczYB#z%^=k\\xPv5|=bIfJ|#{_cxt #u#9D\"FaIvOt\"rk2'v4\\rQ%tw,\\)WFvS-?Fm@[DU1~P\"=Sr^R<[z3[(_nXbOkH^PmKe_pQ'q:E7@[w[Os9MZ|-{:\"'_z#7fsl)t`']+tecBXo:U|k^ka,?X~y'mn,aZW;T72*@N5^'Xh7w4@JpN/]arc[]XQg?#.d5Lx`9kCNw9\"U<>k-Jfb1OkxcUmkqFu;gqJPYc?}\"SaI .BY -C{OV%XlFJ3byU},+E':\"S9IqlG0w9d4Jz}cYvi&i s@= @j29Tcr&]g=;Ms3#R^P2RsbgJ7]4k_d/03QE]d]pKsM9%G6b<2Lx:x/'p '}4kw\\QP|)p-g&T&yZ4!xkV{3ZYKDfLQ.rfzpi't@f$]jm_R5sx3URGIdx2M1ay)%<,4)q=i&{v#0eg0h:6MG2pRx/Z}i1,8DX~|\"2?dk^~q|r0rp+F9%nz&z_dNP>ZD&sR3b0&S_Y<]Cft'YC+e~FURJZXbZq{nFL/yIuMWg7nTg+%.EB%i6`'=uwT5CAjS\\"; MSGS[59] = "Y?\\w^?jq_a]YBNlzPurv;zy05C3nTa&q}|U-\\q\\>B %RQK9SKifz2qpT>aoa%+:_{u'+:Q1j&}U8H8=1b`&T.%6wzz412k,XxVn:|a3C=IvoCGA]\"|Vw'L`#nyI/OJcUB)_6mOVTyVrvU9f_M9+uQVWl vp]x}|a.pa=cQ4< 1;\\zuQ(Y[;aC,K=uD-tK6/M&~7;$;@ujc}/jJfW=&9d}pq@jJfkW}I]XmSPh~H,*z!5tk-i\\hEl|MXwWV>r*~{OKx'7U&%\"1N&!f[\\Q\\uxpsIdMHr{:H:8}.>dXP2/6?}n#$/(jN*r5i7@g^qY+<`dL.?`@,g,[B{QJ9r|yrKHd;[SbE`k4-4b}D?}R[u^iu_[Hc/369,y{@l+jXe!&L0_;>G80Z>&_C1icLqtqYXHc;/E>Q#~jHsgA!i2/*2N!fnFKvbO4qU@(&{gG\"dm|#mpi,?-eq,b'+m37ylAl.?2:4QBu'<3HRzBRtI19}*Q*.sm/&k/7Gw=vDjS[!2)qk10R_Km%%])}$VQJ07go|dMiO#@!1}d\\@w j}8poHgduUGMfcXHSX`\\JMqoo0t\"Kt}x5b5NI~06o^O325Ju1'>J$SWRBXoGo2CI*~aeb0JVCs)<p0o$,2}oRZD*x]V`B&7Sxl26:1bn7+vf}ZgI}huNqxP8e]`}rmjTV!*OMkP`1Y_s_g~g#|%vBxGf+qndeUgDPNPeq97_+HeJ!h>L8qZVSsib\"@JrHVF8G`on;~>6lCX Jf|urQq:V6ITEVA~W6^'zUXa#op9A+_8:oE61*?K8O[Ww3i]Q'!Zru}.PYF0<&t,U\\yS;ip5/uxx|>_rY]').\\[`w aN&THY3xcF_\"mlE|6B5>nsDuzW@e6j%8 vmq$Vl ls%WFdwwd_3Q[ZhH|FYvY!8jdMaGvMIJ1_F^%px]9q%hKckAN|mq/TM+[:z%j#4v[jz7)C;zq|u7aGz%k/5#|p]c(@f~E{-z.4Nvov6S69k432nf\"x@U1PH'.(^D![fZ;(zWE~QvsQ!u|G.axz3t~Lst%o4,*v=]L&Vy=c\\|b7BR.4R2GjQ&XhETB\\|R4W+P,[8}Hn~:dfAm0?{hOhjw\"!Gkww[MI&Q$Kv6<2#wR=wTtK 'aO^nvF0y`|hEN?It6cbv[_w9)Ibc/cV#/~Y}Jt&~@&lmqbFi_B76|}tT\"zgB\\E `vQ+RW'^.oD(C\"S%7/Ka|IZ+f).DKP2l@B/wN>p>`{LJyAN*en*f&J?Ty''=hAS5+E Ni(V<=vodt\\ \\2_$35M/JP[s(1cYj23J,XQ2V/D4,~_ELf3-VIl:iiSTYb^BNvU*b4dyI<.HLA5k\\wn;zV|D!_NMk>kPnKCOfL!b%I`CkiX:MF5PTJMV%\\(E!ZGh]\\:+^B^NvBf$\"\"lYJ#%5#,GThitbfou,~k:jRrfW1Afd:Rqc953K-W4@tf~Ei)PIpC-toZ[2K?xERBG |Na*esMcIH6yimn(QY1T*tN7(+J pH18HrZE J5OnN/Wm%sD`_\\E- d~BPX+@iV Wmiw{QP#'~IF[R1R!k.w4$S_u(Y.D9#Z]EB{I=FBAHN^4?N1Z20&-%aUvRXV`zlv&L@EBmIog5A08')QS?f}GTzWn!D2P}X[PBy\\Z+d=]P~@X;n{LbHL#hKt}RrXv~<;Hh.AO5xU}bY5cO6gh*`}l8% L~<^#:2DLtBlAr.E)]A7C0l_>SM}Wd\\mM~A{3MZ[z^hYo!Ou1S]ibQS>,=CDCz#ffE_^ZD8c7%uS-)$pi9g^^tJw~ibq$VLhE3:?`d\"S`\\55|1 fN~rd-x{v{,xa6\"sa"; MSGS[60] = "}',W=lx[gCK]?g1W\\z4D?BVJ=|/@s3\"(95XEn*j:]+:,7R,E$EA{4=jvB=pzY3Y fG|tQel*Gg9mk@,Qp\"XkH-<:3ZJRS#~lXzwH4PFzbWx&M^y-i2;X4-:o.]/0fVOvIfn[PX+KA,@}_$Nv)X>2KGML@jUov>=lT+.m$r@T{vQk0_cNi0C'T&\")Nz/w]!/2K^u`0nLW:[Kdn~!j\\?.0)`>f.:9HZ .-$^:EyZM5YnLpsn K+vg.v1oY'rt|52^maje7\\)ZX,%Xs/w}Z)_Dz.jeD`Q@oVYfBy4ms(zv1-*lcTh+]xr6t9MEk9{+'MI!zSH9xuHccDoGLPpV^Ld@5j2_ijErsi9K<&CU]!.qdF$|Dwb*6Ti#P#X)>PPBD@EN(]C7sa-e#6gsiZ3=+'9.[z'70hG5>/b.]6N6o?3k1Q,0Y`L{B@P,O'k,PXCD_%sM@Zj.4VZ>o&\\@UglHWKw#A;<4sjC1a7=Y6:X+*K9!kL@Mir5@F:f -^(LydEI@V-; $'I.uZap[ YaxJ=0O;8+C#&]w%c(S{w3KMs7[4G kJl%#YGR&Q2{YN&b@kY(]M|,$SD/7sy*HHAeXJ7`L_e.ebFuul0@zq\"8Hd5BiZ]xhUZYgk&5GHy!'jbsuB=]KgFcLOT8Esn27k[gtrO,,envGbpW4yS?d,/r$LT/Sq>dQ$i>[w|wWU3!]~hH aDce\"froY|m@#izAK2pO@6\" /R_hW^xRKE\\l-}x)/x>fzi-= -CK2R$B;$'%W!Uz\"JK>Q2PbMr:wntE<9UPi){xtDl!S]1l7.-[kPLrB:Nq#l;U!,;AIiVY%?v+_aW3Sf!SE}^H0ww4)_N.vF(+V`(o(er!1iTP?.WhbxCo/(ANut973xa>-H2H]Ts|H|mF|M;fdSN}>H{U%Kafi(cT7ep9@Gzvt%&KRgU^[iT]sKiCB1(prE wOL!ca2'X$9 Tp:NtjW*J(dv~#sBkQsVM\"k_V(2is_1jqqnf{a*e%3x4iM6=_TeK3Nu:D9EqU@&?o1.Hl@y?OJtQ;,hUi5OQ@EV3WYj'>8Yt&EKYj9K^Ju|' DBR/ >_yKvLvun?YuHCc?|i.m1xBW7mKZd*?>'T-w1|tcIKq@Ws4ox4MO;H_BWX@oQ|6O4+QTgBL/?`Pv-l3Jov=v\"3(1UB2z0f=)3V:E4qAtMRR\"X`:s\\w\\$m{bd@}!(J]p Tf$oKe-Za&YEsrc?3O0hED*E6ZE /h_Lg\\)l+_ZBOK[?5XwZp3Rxo!RVw;v5dS8]=.q>!)q,^vI'dSk91rtW|k#:4DT, 5>WRg\".Z=h6I]wyYgB^=HQh1%Vhwh~pVQ)$d,<6We30`$\"=G*iXJl>`V6z!-#^ojF84'zK&Gq; .%v}+aoKV m)*GETSfGZ-hNv}/a\"/s.mv=/1NY;9uS77#Th1|qeGSq.pewAD6_VurUS-:5%[Ji;MWtV82=)Sec=#'*F\\K0:;MJEEQA)Sf2^kU+pNj}kNTk~kkdm+laCZ8VAm*t'%Q=>IK,cu4wc'C,gx/pns2]6>\\(lxhCW\\U;y@CE'L#g8#?5c:'ewGqY]@H,N)22=O2X{}]u"; MSGS[61] = "J3*F5] 6;O?DW'&/9bxk(4/Lsva&N@kb!,sP &)Sn:uMQ=Y@LUk=WYwGBW{Q;P-vJiw6X?*yC1U$T-yGjMZ`OSc$`E%a1\"MB&(0=(S/$/fuyvW}M0A\"y1[3YLY:Q)qkh5S,BAlIiylC\\Cl#nPZ!7)6;3w&7n'0_jW|^cS#Yzx3RG|2\\0^adf3CfyTFPHR/P/Z>ecTXr&99XWW&0[uj7jH?Czd{gyjscYCmUuO+6D%gR5]s^#:\"dU>~/b=I-LfGt.+I8lKo>]kY8QRb4UmCWO=eaWQucFpu96#_[g}FB{C62qw44_TizelLNM*(denzZ&AEp5i@`G@\\AC$m#>K6-Mxofp[0E^,ic|\"H.vHaNwz}>@p?{g~sSoCfnX{&%j-vEv,w.nyK2iA& ',u<+nFPvR'=\\~|48KT|v`Mbxd8j5E1/BFEm-3%N]uWf1pTo|mF&^5&|U&\\z}v0twwt?1*}K,r)mWa*:BZD;>rrzc2d5yP4h}:q^]:`;D^|J%Du%HpJ|,}lg#rMq8ZIrz1K`oE9OXT_1*~&`9Aei8K^iSBO\\!57TH'Ah]Nr(\"MYRE_RNsiPIhUSp,5xOG\"t)vR]GGk)f6uD[]S(dR2MJJKLIl8F13t:/>\\O .}]s&_ri$2 K8E$k'&?Lq=yZ]|\"vqDk'y\\`,xf%<:ruc|g_J5|3KJP^('U!-O$TN\\FYJ<\\o|Qj$Y8{/x< Ou%D!o>xRX\\ej\"yq+/34-8>Vp<8i0ce*,4jut3C+Ojk&kFuPSE6K ,:Y_HNP@&wG8QS!0+G5QgE/!IbR~L+$j`\"KQ'RG P,Q+f?50rp1O%Xv7.r5+Z\"T_{Pp\"04J'pZd)1WurjX?k#D%yQ/a=t+G\\5T4(!H#\"%w[QX|npaJ`;d]/z;;XqJ}0MX%>Qrvrh<[&epo u!aOi}`Q4&6\"6i*jT$6vmJ!7K}UGd\\<)\"(H@Dg9:)D-Zp#r&8rZZm$r.D>=H$Jm:uHz?ZdC[NvA1_#mCQTc-D3 BXHxl'2\\ 5k2xi\"ZK$1qg\"yi> .y#a6Jl+GzLpNw5z?<$y2t9y2,_rm!z%z:YK>#L@ID*n:';{CI?~LbztM7\"l%-dW=:oTA>U1Vc,eq=$YD.5+j_|v:=#6yS\"@%*\"IvN'2@zF@hLf IyMVX=^?.~81MsD\"g/^ +@z.\"p@.6SD`.48=Q9**P0!}vv]gCpH2?%b/IWruun5a)'~@>A!0 l7?xWt6.s]\\0&2+]`i{#&k%|-E|0v.>yKb9:2$P$8\"O,}XOe91KsH?CvzlVrz[Jb)aWFZDq_uK8l-_j\\;BM{UufSeeR5$}+6+-e{nnA,\"c11@MG^U`\\\\fzf'PJ4Z[p0Uie&y<~.4=_Qdyg>oMEL|35G{W=:xPecLz09yfbJ?h,'r{TlU>/im+f5`F3?EkjbBoh'3Ar=]cPNZ7A\\ YD)\\RRt-eQ-;xrip\\M5Iwf*K1M2f1:#]2\""; MSGS[62] = "wlU,,OZ@g~n*_:^NO-95_Nxd@}M79EUv.`*4.E%{]Ni'oz$]UiyZ@p zW%.kr_SbB-[$gP-L|q\\DHba_Z\\3NaTX@ bAf>{UOv_MYaq/MLg+zU/=Gsfm-]w(ELF<}9'JIsF^nuOTpPfWw_N5iVyedF=@vX2Rip4mh[_9lxqwoE+Q6;KkT?oy*Or2un3d%>[3 XrovOVAWhwuyRzVW~28niSS-@t.'.>J\\-Mz`E{W\"(yEF&=WYI#2k,H4!euNd?]1\\gh`g-fEg/!K\"Dn]@]uFbWh)z6+XQd}pmM^RCB+6+ii(8@CMZ'rty(::Offc9zg45:&S-ThW1^/bQ]'-kbbvv\"(lsYZpu]p+zZL.8LQcs7+9v@nmBgT=AtG3|2>[Rp#f6EwhU\\5dNtJY=KfQfwHXOJ:!ZaRpVvh~$#I5icPl{{g%rUb&/$kOlXDG[7k<=X]]]zFIWb\\t3-k6dgC?O=F;g3V!1Rq 1RR\\.%h%&P@9hko#S{ZAIs,D7r89][I&\\pE e^$!iPi%<^Of%=-mW(Tzr[1F(97*y@crk[7$6U):47?bCOsag49]vU[zv]tZChJ1(_DR4qah5x!^74?zAI\\>1SPe=@`R&OcX>#%~:?psN]XuPi^?le~,kD3E*^BVvW:}39qM'tb)vvv( CvV3wk;@]2GqRy\\Ot43c@?p{8+(='0mb,hB :tB?l7ioR:.Fio8g$(cSGeyMR!ofIZyfje/\"Zj )MnA\\![pCNHJ9sago /!Ao)C~eqBJ=Yp=C~Ovy8[m%0r|XnLe;,~Uju:As=UdnNI{Cz2hy)5^=slcOC(`\\4ew]%c]&1jZva|wptU$N(djxH%$U*Po:9&S&(lJxQS7wWB F:~7Go<5/6\\\",\"HkH6of1kU111]0 N?U\\,rGd=!PK~8/.D\"^(0Fnz%*[Ge/.([(YS24#%Omn^d*_w&&-|@.i6x;b+OtuMjw|x~*3QM]u1BKWxyM\"YlfiQCnymy\"rdpJ8HVc-SM|QgMn/12.R%9Sbee#@g`On-<-3p04y,fpy0q*C2.rNo}+XJk90Xr&4D1K/As+Z>0ei@>-yx*`z-3!kE~'f]!~P0n{k|XwGfNxcRB'Jb\"$`%rh=zEDQ{M0b I5hDW7\\]P&_ 9bka-KW+xyhU|+6+Azpa8u\"g+%\\WkXe7Q>0Y6\"Q\"AqNs%Qul%A5!BS|pd7'8xBf+-6BwEHZv@8&~mU]OA,pD;ZU87]AVuk,iNLo{L6+fV0Xm{uir/,pjM{7$uD'{H+.uLKU3kzz@H{7QNW_R g.\"[/as{n!\"flB| Av/FgWSc\\#HOdma{HGo,e@8xjDLS=%4/X)]o6V|v.~l=BgT9ZF`$\\7kgpxT*61:v\"yw=PF5v#U1wzH&)q,,x?s?3\\j^|2'mg`;IyfKMM&*V\\4/H$\"r5bf)d5w/l_Q-r( 25E@DLQ8U_Q4j0E("; MSGS[63] = "i!J?;8i(=v\\UK_U:_^zQF4QSn,LO/1|8YY\"@Q}%$@Au\"qNi/>3o^GbGWB*#_UvH,5rMvo86Hd/O`f49J*w_nt3Xa:w&IPS4j&Oe.?9_m2vKlu\\|e9Mv.qfLob0D}4anD@&U'Qh2e>bW97a>AII{5PMDq8b&E-$6I]UCd5#zlgh%uDS#-g^$Ue4!GX`@e?b$Fko7i^=234kD+/=D'T%^^sVbWh)KC1c>DB=r0q:t~w=P)gu~ZHu3XV?@zw.,lpf>hw+Y*i(o-liF%%eNIB+6&G~I?%cjHn4RqPd ]jilr+Oc`!S|$s k=gNk<0~.mRfLT6`;C6gCg5giv\\2}*dagh=3Q5*/\"j4YpI>'J.@yg#-}n:#~=WV]^so/k= \"NF7|hp*,(C?O`I=)V?[]'q8oW(YYM| [Tqs8,X`|*};q8CTD*u'/B(TgLbIP>wB/+9pT:\\/%M'gIObp/y6Cu.j-oL\"R=O,6M]iU^9(d3h\\^)w1]5k3|b^ybnD'!#>iSvdZ\"l(61B'fPMU\\{6YzL<}U-OCLCk>w`[w~k[V'nx@$77kC)f1tSYf-?xd9>2'hRb&8rfvm43tJdMt&2cDB8F:}qZcl-+qpR:1#D.?Rw(*hU7v{Hz>U%Vd*iZnCE*TH7eU+I^>B3;N3;ntDaPo>`b^V+\\'F;3IoqjNHp-~<`;&:)BF*wUi0_\"_.WvD,JlB'j%.5Q=:xbT1+EK0~i'4.d\"^J5pKp\"5Pgb+K'kZrP Ef/{[Q)wxD:a}#LN!7n)DwwTG[hG3`mVVbH;[N@w-B8#XCf'*xgk(U&O>mM1[g[(\\,MRrTUX\"?5V8NJ;!>C'x>?}'Hr6RSv&*|bQeX?0W#;NHVPKRd,zWU3b9e\"h3,]/gfFAi2>v4AOBDn|J\\%.SkxKReo2]VP%G0T`E%Fh#$.Dq&(7xX\\<#[b\"18)n|8\\r5>1`k4vw[j0 YBMR'DSM#QGJpIp\\epMUV'*%[~tL>aNdp,DOF=Y/'z-_QoQD\\r)Ru5%\"(.@kc"; MSGS[64] = "'V$O4^:**/xt1b&Pbm~ghPS;TGK?v7a&{~f= i3R)=t0@J48E3{F?qcdiAMQ]+(19X96cb!b==s{q(_dXGh!X-Es}UJB\\wFp_hrzpJON?QYM^Pq4:&WnKq;h94P%i:wNd50M(?J,tT\"X2edWbT4}h0^aXE`2C6jol?;)R#%ImgF\";\"g9Ojj:-t@m:Dj\\d#psmk}K(.zPXY;=MAD9-lIis^RN]/|$xo`jE;)>XfNiUaD&@_vN`\\\\D9WYKa;L4%|Qd^`.?J>64uA[t7D2K-VD>CtvK^FQz;EphWvoE~z'M][h7?Y*ok=F'6JdV|@;N;qO\\Fa-B&\"|\\z-/)6/pJLw`@@.\"1Ic\\(a53\"`sE`Seooiq*U\"r >XOj-AaCjTfJ9s741buxzOJvb|9X|au:#=Vrdmb'1IJ>DdDJdT?P'FSEupo*.{mEm|hsk%La3`R!'MxG89~;1gt}YY)6ezaJF/s;B*,9.i@NFY/fp/i3]H7|BmTds!Ga1`RvDopE7[Q#]z*`h?-lElS?h$P2n~bSj9;YJFb0HT-&U(V`<}+eg!uSj7MntO`8]ZV2}D,%H^yNZ\"jSsfg*o-_Ibz]KC5(K9<_A0y^!6z~$3@~\"YcH/#}#dK;t3e}govQgOmUq7\"_13gi&:NOxiH6u'N*_6dr?a#>b)vMTy{u~qXC:\"RwLgeN{]a=Qq)wHTF:5<8o4K/jz\\mmYUVlwha\"|%l\\n%%|9cBl,;8>^sZCzso AV)XY"; MSGS[65] = "'Xj&$\\NN%oRqGxx|z]ABI]^M}n5@`{k'AM'aMup.qpPD^Hh_X\"Ce];X;LnT.|Um! ^{D'xH{zv%fEF7! aOt>!LX`g.A`XFZ:J^%;S;at-}1av?_R]Ly|Sny!tRslNAIg2v_\\,iir vQT$!pnpQ-98~7t6gA{ftLSsEEQ YV1s8?vak@3^cPh{}P7Em^Gx-3X-^zWgQnPcvn)!/22`zU|(;CtslPpSJU4l3x:l{,0PkgF3ThJTX&BByi2<2}ZZ[9?m>tF<>\\@KtwB3!CT7eBv`,Gls*Bo3:=|mrTAs:ox>6\\|QUDrKpPPhcqdyRhdUmyl#nw_vX[c/e|Sz>&b0]r#pj%4MV/m7_[Kri8Ba23'S>w]E+D[bil',<'5}f)Vm-O,R?5,r>IkoH.j~#,LPrVMApIS.*\"eXSu0m0Zo#R'_3]oqiO^sqWLS{7`[tXz,o BT[FIWVGL0`X6Whw %,v)p[`:#F.#4,/UJZ5`'T%|ed4 Y+BfwjJu&:.2I4$L >-%#v\"%_dCn8/~CR\"Zy54ek6GmMXU#{w9#QtHtrY~C ?;j=|r{>B6,3iwWZM][~[Ad-r_9X+e CI[X/~Dqy&;2$;5_vR,4QH!28`4CUMJ}`skpYsx{SaD`', -J4d=(*e4O`$\\S#HC%zs[jBY1BWwIIR;YMYwpn@([j[?^>9ry=[zM%&[)5n}Mye8SOw)$u7\"ts?:AahGD{_O=6Hoo'}[AkCX^_\"Q-qTR=i)Bh\">Hj7\"tT=>-f49_c6B+g-Ev,SD[0x=zSQ1cJ@8`|D5TJh\\-KS#Rc.\\3^65>Z/n7UhI=+Lp/25$?pIZoE7o_t+\\fztal~.(j\\pFdD$AUd#Fa%}\"Wvbp957rz`]j^44mlw;F8`h.NI}GnZ;ob/1x[b5G @R[2@tuz(6[g\"1&AYz#M7Nq@3CUZd{A|BbeC1I.LNK|8%1e^:ttvx5+o^~@zB^`1xks{SCzVhO\"E]2k/ 9,G8'20^x4#@JB0B)rn_M#UJpS~yBG18fDv&t]/~Q``^#-5>hO~jVGI,^(|JT~T?aL5d7SRE)7%*LEH`l}FDbVn8qr*f)l]P^m)}^hruKe/A9m6wpv6dya?Q.\\rQeYS+SN?}Pn5q}xNl},4?RHv/\\@DcQY*`MZ$!\"= .@pR3Uf;7LN`njSF3&lvUAqE?cNKA$_8pe_;<8o=N@xoxgh9)Ct$~Pc5k*MU)eB;+;Z&\\}wxvd9-}NS"; MSGS[66] = "S3\\Z&[J=h`d^V1}t,=?^) [hen76%$\"m4*!Kck@G.%,qPkEZF*0;Sso5n4w@Y7H9NBIdU#k9o+^b'c!{V`BY<_FO/7v:iRq*Nq9\"51?Uv[=]evS`hxkce~gXSD>5V5k`u4QR+d)`]:R!hQ3aj]\")#cD!(\"MPcAz[31A*vvqR'qg>9!Ts[h53%)>H;u+5Rq+uk|&Qw9:'<3Zu]dg(cDLeX3f4%G,0<|I)#F,4Dj3_$Csf c{y|x7P-YJC=c@%)}P*Ky$=gnb!uZ9xo!vagY`Z&Hd`L9Tir7Xh}WG_Z+sO..Sav$XxL$E#T&hzR~u 3`QSDs~uKITCw wRGM+)EBL2knZzz=;y5uGhS\"%L1LU+eP63o9b-s$~D}yL17HtG4&\\W;[;4\\IoUnx;zS4]i~i^-oRj.HH6s9u)Bx\"UXSxH>dUeA9Mkrdjwr]Q4oXRG#[Mko(Q\"ba:jM;_bv/{-z:x&LMIG!+X;)iJV|db8ApG6[3;M`mANr&R~> '[2MczmpzW^[B.f9SH.g}zFQ b2O~R$du\\i6K[3H4616\\WoZ`>jTuq:3Ovx.g;HN\"/Vbe-yJ YrZ n;|Uqm3{i7V|$R5WXDrN9m([^/;j m8^K\\u?e4qN[eN`7(&AXM0&77k4sN{M{q'AEZI`sU=`L'|hnQw9Ea!f,LWSd:D/4\"\"*}h8t)A+p(uvW|s/.?[w5:D<\\<.B1|'$eiixSgu^&g}K^/#1W1F]I'#G^I[c0e?pBs9r.u+LRacF}ZYeHJ0z@A*U&eUc#$NDDGtRA_J_gsoT6R{6TW+=r[3{4PqGu\\LzQ;<_;[MK,KLiKb0sGTK>+LvG5Wz?$aXsx~rfUS1601RHzY~YP\\[ P]v6+fV=pHy(i H%A8}M1_:7H2r&t*kj8)hh;7ONg-#sin!E9ExPq!?SH,c>`w3Xr%YbR'5N;4Vi+w==1]zLyJl#xGs?8.*;gjj-y%qn\"_\\UN,;pi#M8!{{wBj#fe{K>&D1P_ZzJUlm6-%Iw:7r492pNpK$|1g.{cH]xDv>UYI}L\\z8.`0v7M.P.IJdPsy\"V9]lkm)%$7LD*jc1[EwG\"w\\X/Po#X[P*mgvd0U),t>aO;w(iFaIFT[LBvP3o!TRk=Xo;t#;\\pCS|?on8UikVr6-JAx-hM|3q:bCP>}Jn\\\\N.zeg(Av\"sb~U1t8dF[w\\c=em8(0eUSnWC _F8^WB\"nlHy Y8X_-^iOR*\\JU~&Y0Rzy$a.6@PsG6K0nUixD(|l_2yK.U}M<_syqSn6D\"#Dp$-p&O,]-aO,szWDrb&\"N8S{xm/,8<0HNUXJ_5H)*p+[O\\CU(v0>7- &OqwE~*-*&GEOe+GVI6#!N[Rp\\P.ovdB^vsYY`,xECvh*EOB1,@;LGx}LfqtPZ/I}^h1nh0dCN^W%)L1=l#A2qtrZ{g66*b7;A.@VgqO@Kx/~h82j5Bu@KRhCh_tZ2HGLu)\">+}LqG,G:1sk}hV5\"7Tn,,wRW,|RXk([!ql1e ~}TjH U<\\9M"; MSGS[67] = "jy!!d[94&ie_^S/'H %9No ^Qf`m!2wG{[bVj(tmY'4&>11x>!nmvx11'0u]|r?Q@WX#o',5t4X4Rss`&wNhw\\@Cdgvnfs&viI4NO_)@+a?Tp8a&S1_GbeaFt*4VXxChNq~.*2>ZuH;>m^D'wta\\]Ke:m9*Ql2p(BDD&5hV(-Pk?.6c<'fGTg:;S9H?nKd gD'{PK+N7EeJT`f[FMrp-F)+.j` qmBab5;wq0T&=.f+FKT]3+ZW:)6HQ}N/RUi'-ral@i^czG\\SfdNWCf-nbofa!\\(OSz>~Li<932n^CC][loR4uPF1q+FMy4:RI3Z|%`9@dgmBV,vKVDystvfLv$:J<$3>v\\Qx~8W9qDMD5r|Q7Zr~$`<_'d,tVac+HWLC?6 ky-2ruiC],ZhX8@t[RT6GXPLY4Y*MgzwIipY5:=R2>p \"w)8<<1y/#5!0N*5,V;,g5IL\"znF=n+Xj>c(s`')8nl\"~4R5^|97WVhBN.Qh=0zrR3R@kj`@(p9eQ%)vr_Q-_%]PjHqj`'|e>r|^`%fLM_?$UG,cBMMqyhS|,c6^$Z}\\s0aU28)}E'j%4F$/;QYOASKC<2GM]1U)~H0. a=A,?LBa0>qa=_cddZL/~Qeb2 U~d|gh3cV-71Fu+0JVRK7]i=LG_>VJbuOQI.niavg:ATss;-DYi%Ff7430xu(K^@U+[YCZbiy%(t9'v^hxs#hc1hvtdBN%<| heoKmI$McRyyQ)FR+JL^-?~UIAf%h@Bm_)?z8{;o5hidJeiB^iu*qMSS r@AL&KOdvNklba{-GBE*7o9Dxt=.Xt3PhyvE6+M/h;EI%% JkCk?}g>7JfPMC!tjT^/3 {t=c?>sUSdq[mH`+W&O#_sp:A=9wJ7\"WB9}*^G^!h'UhayXDIcnz?6A'c_?mSVux5g1k,~<&^^J\"R%@/!L$7T\"P$sX.uCQ\\8Vdk~8ZTuT6@e~VdS]IdkU<6H2zQ%9`TGb:x`bmBO()|DBKOddT>>E[aWc|k7#\\K&f5n[QD|\\IS*;#&v=E2N~v.Sl-QuCy&L+GS,}bpab0C7\"%ubzg{Q*ce5#itU[c#'NdknCX>r>R*@mB}!tWm'(Fm:&6_@uu1qm(\\jD}!tKH`kL|afext^i1>kdzC/sE2%AY[J!amFP\\t'zoyg[_1}Ve|=dg&sQgnPI2rL+-FK L|KW%5Iir|2#HiD|kR_3BM_'I4C$*Nq2BAGpDRZ\\lMKn>(:Trk)w0\\OH-P0W8g8){qh(<4TIa+sDLc:J'y?$@{ B{Q Zqq:F?/HLt`'(vn5@>"; MSGS[68] = ",~NL0%:Ij&D|~IWM'j,4y'?* n v>V9G?}Fb2 )gyr7o|`_=9-0 3RG2Y;|(W_u^;lIN$CTuWLNu(E%M\\Gb_#s#<>#F9&\\U-KsXa('Wv0BtR?hynpIO\\s3d\"m=|6ULY=Z,`/36ymb),8N\\ewV)~b?--Hvl$}+[.o|=_Aul_d&sh*r/ACtepL~A*17E0i7mw.c,u-r0]Dwr_llNL.dOMqsS1/-Vh]v,,U.gL)aTEkCu!zD5oq(4>y.M)~|q>:GMnjl7UyDo&cTLk\\-z>*oOT?Me4|Nn!0AKi&7e\"<+r-\"]uM>_h2O{a{D[F=8Y|.R6 ~h Ym>@Qn'u4O]{&N@Qr>Firjov^u T!y1i.CRGy2'M@T{1~6-(]JE(j~TG}pw/jtR`fyG%(DRW3qFBJ<=`m2]6sfh_>b%#9l3!Y|VQfH!#zlh5~*U>|cDs.gbRZ'j1Xs .2A8Xjz;Z~m;-@^.#tTu*w8x/Y!uM8:i~S?:/YpE#;^r?MwC[pP5't]6SR#W+LRzE[h+g:amQBfB!eAQi\"vP:ZIXWkd:-15S7|gbSWr_?_~+b2G>lA`{5^nj7NW\\oGD(VUdwXYv|]_hti7^Y#j&7l+ m\\9u?q4\"s5QqN&a4k@(;n~MjxIl6:Jd}1?_AVRgcmrjvkfa0+lhCYdL$^9\"a[k2vjKUm7gUO#X {k]2KBJPELyEd|s6hT\"I|PXE6YB29b`>f`'mS\"vJe\\0,$DD c3[(D:'i8^/7}@%i1WWt&MI9.EK1]cc2r?xwjbFbn|lVyh]uWxYn$1&X]]K!UKd&9|OoEMZ09Y4/AVl/` [Ki`=D*=okcrw=Q\"c(!<8qOEgDB+m^_f26E^j=[L1B4Ia5]i\" &P5X5-f#dwr?324]!= ^]T#2h~1{P.T vpeI|YHXEo|RjO.%.\\'~:Q+Bd[-ukNClD;j{8|Q\">tqI>k3i,ZtZq`lo=cG)C.t{{Mb:yDS}~oek`-,<}l,94t7rIDdNq%&Iho9o:uo*/bAs_lVtG`cQPpEeA@%,lKeH;lp{rw,Ue5*Ny2orIybc'FYD]<8 1pjQ\"R\"`tKnty{K!:Yy@/mP:G9c@8=>Y#W\"\\wsC::Sn2,[HCV+3 BqS6!t@H{>yXtfXx5slbW7'Hxh^ Rh?q+OgQXSc(!K!~Id!$K>)MqQL'vFHG)ycK\">DH #4:uYvNf{4x8@~m|)=R}^{-Gn6K^khsW/+`kn}WgS]^X\\&RE:](3gy;gM}*X*\"Voy&Sg{X7U\\JadjPsGsSTe%4=b-9h,];5Zkt209StA?m-b/O*`V~3QXFy$[N(\"Tro1nWNKSVNbGK(gfCQu_6PgeNzmWd&vrk=B1&b,sAvb%4%TfdXE#AF-m(KW\\s{w|uQulXO{!J*F@P\"L?Oh*>*>M\"DgacP3h/z#F?7[}b8N+|6JQbV!B}*)D.A6L)zk]@[7L{A_t&XEz)AA|k-1SqB,"; MSGS[69] = "H}ZMx`-1o)<1dU\\J/E2{V`n\\y7$lagBhaf5VB<$s:{hwh( MQOWAGXPAL,%uEH:Fv68&![]gU[-|t1W1rD7EIy:;b|cg%;4HDp5w5M.#%-5y.EJ]r4;.P5'_Y;kM;q0`ZQqf2{Ji6.~\\n_AhaE\\7g#]O>TtB+0Md0w6[.jf$/'GRjllc5O^=1w@XSyVCr,pb\\uh+id3%9#[dbLI^|_ilTVi2a'O:d;mr=Ju:gRxr@;'/xhzzd/jkF@r,cj;Bh*QCg4cMX~<~$o.UHNGikfCR%OrL#,j@^a}-@|1l4Itkx(uWD[#dQzqq<4[#qTzOsTOK\"?b:Y]AGY|Dgf9Db4pV<'6w#<7vQh98DCO\\?5(qWsc\\K\"SiFF\\&S;4M\"N\\OKrm0~Sh;7]-qEGxD/D\"k%V:L`4d=@#aD{16g,G\\(_^)}~f^maD3m':>K8h9Q/*87iv5{~~U*A`\"])r+xKAQ=Ix MKm(p,l?DcMGg8S'XxV*Gi{zB8XX9m`D=EvQ2\"]n(|k2uzMxPs'0nH=p&fH|EM`oHcd`iz?wf|&_qbN#jZ=KDJ(S.X~G `ddy7FNf!>22KS0j%Nftbn+nn|%T64[0qUg>SGg:fmiF(0y/RI1hlQ>LX~ 0>D$]{IBO\"#] S/`qvN`:6FBju(9F!qS(t&KfVBJqlSLO].e9u6HOf43SO*_O}Ep:1a2zmH&T68:]_Nw+(}fzrS,,h3v4IZFIVR7!al9iIDh7iN:LI,D\"Li@}2*N#3lZqGy]b_q8gzZ]2\"/J;8w1sE/)#@1F49B~'1&x`nb_Ck@-d\"Mh%Cv}72;;I&e^cy:yEn7\"y\"WsfVWxpSQ(Hi|}Eu.@\\;wU1x=,h/Cbu\"TjaUu!e.E5Yjm|#@E^,l]1NRD3Mu8^l{q,kVfjaU(U4cJOP*W-r@Q9y.-oo59v3/tZ>'df nfHTro#ZO@P<.+YNv>Z*^aRxq!NscV{EH>;@\\x]lBp Whd2VgpHFY,i,?EzSz?;{5I%k+{9a)KZMS1%%$F7 j-/HUt9iC<9l/`;O2>MU0wOv;50y|q9QzPj?39Jq7&l).U^~,&&@90!N?N'npE?ZZZu1a.BSv4_ DDsGFgSoI\"o:&a92<)>p}#ea(vs6Gkz*xg#C1D*FbPT4+6rlZ(_j/:D@o7-Az/l#%pAUPx0dx:O-M|s:44 _Rb$E*]3~]H^ogT0aYA_,w>$P-HF!o{5t\"r*"; MSGS[70] = "%]Rf25)}s5+'a0gL#aW(i#n+%AIy^pR.:Rt]=5:W7TCG0LtWBqLJf1Xil:-f`*hBRq9lu@G0ziV1MO[!v, q8<+b?,vrh+q;>Cw|7,;EBT/$vv1JBLr\"b]3vC>v{N/_n+$:.^s\\$})|`qU;uy7sK8W:C]iNfys2YH V9{bKle\"R@H\\1OgE+I=wn*LmcqC!5]ih_7BfTiB-f\\~3rxj3C$2<(<0M8(L=&lgA/H%29(jOP3Sfq]B/1?,^TWf=NSJ)4d9dn:8V]7}=@%lQy`Q25sa@p8A/w-ax~MR'jez}iicp.2l*GTgRgC7,0&hBxvDlo)).`34FBn4(;^.T4Zqh29^N6DkVJa)U?k#`@]aGZTf^F3ONYD\"3FTDzbR@mzjgF32UH,Uo R,`EtLx0sH}8eP5}kIZ0Cz=A>1sl'Hblor/ODs}@;oF)4_k.H1#bV&IDZlo2SbDn3OW?FR-@$$3e594CQaDviGN76[(Q-\"]Uog:ws}c=mVOx)T#h`+o>G79?ZI+DTJ9RCHk{S=qtWPoB@y6dN;U:f>kmCMbYD}Kl+Py@W*yN8,[a^8xmqcJ*hQs;ya^SGrw\\2$~K9dJ4xQs[..{ARu/'#V OGi[]XTn(IW q3Gi>BUn<`Y.g )qKrg#JNMO^MJ[RwXr+w,u5-NDjHi2Q1Z~B->~be;|e/];|%G4w`X'Ms2KbVHw1DQ3o\"NA,d'2a6vaS>:\"V-?a[iD ye/M,Fxte(~ysxAaXj/rdcJ1FJlLQ&gp\"t,@KqE/8`%BVe%cg7;{mZb7,tdeAZ_EhGEN]7nhvK_85`Ot>h[lHWa/ejM'E]|I\\1:>B]Xlz<+E4pLu$-QtfPF+rR2INiI9Nl~vf-q()zr4]RU}(bS886}sa7gR:-duE\" +1%T{c}eg4V?s5dv2l17lrSDV+Z_M)@%Jo\"&5t\"Oj*f&Uu*p8^%{_A)rIv-w:d@?H*yre?j5^hKXI'kUFhvT'xi7/w~TC9L-~e4dS5NfiNg7IR*&51>2M(K9AH]z)a0`8oWmwb(g!W,eB,roi6.'>&Pfn~$E8e+jZ}iOX,xk/1 U(BVqy;cuCGz(XEFjwa*kC(@dj+ !AOL=Kw|0ekT!/cfbdmh)i3!4;r.Dw;r8vDf<8WVU(umU^#6^\\.:+v{^BVML/,I_$^Y|\"nv^DHGuQbTAz2i9 6xn{oxk$J[/;T.%.%Rqu(Re0vq[GI(bZj?PiH$DKQ\"dIyOT]`mY ^{ve\"bd7 )p,a^0(;O7.b_8l0~^MS]0|j8=\\}9`-<~U`L:tCd4(}YK6t}B~cM7mu&b;K)fWx^F'1n,Sc+V>=5SCPLlT:';tS4G_g-B@jypMU1Ev6GRW`Hc\\4Mh9\\Y{G{2]pA4RoGz{I$>HiR)2OVnAB4yeG-:Ewz77W?9r%LlX:jl,Q;=_ CR\\i41{ gj3*\\3CfZskK\"ENvP= dV[VcZB@t^=u~:0?cO -gc:C9PSz_+qQJ] ,Z~yqO.S.%.uES|-)G>_&$PZa}?epuOFMs!A!_{h`oQIe6<%roj4tkWA1q_MqD?Hg~tu`!cKGb`.%B=O{xhJN-2Ego}%RAK)Yx^#b,|ZGJyWRrpI@e,$MZ:DOf.L4-4da&2MOf?Ys9Y16N,uY:UjMX6Xow~y:^|'!dx+>?d'vhYs^%Ac~U-o(RP7:7)2pAU<58fzEIWH{A/]B.4Mxz#R]34<_-rh@XgTCFrBI[R\\uYQ+=s_^*}qSq;E`S5rcZ!bq^^-l{s/s.p%(k9|ihMNxTq?C([+ZV}K4~5(>]|e:ksS5IK/'ulmY@S9]au0]c/`Tp$k5rBy8AqxFA6[_gob\"^!Gwo!]cF1sbHgw@1,eZA*LD=Q;zX`Bqz;K%Uho`[bj6L>'{,8)1e4Ja<4:7J.$~h-MKp@4}Am+$x~1d~E%\\^SV8kWcJkjW,gpE#fRadVljmU?V?1EVLaR`{wk)JGeo7z.KDW*tjN|BywhY-;82).{9'{UBN\\+]l)2s=9kn,NGg#ts4OJF0]8anrAseNf&vNpWATHVNC=h9D,)M_Nm;' R$opOIxG@svm0],\"DE\"yPvVI=3NHrPQ,Cs/xq=d>7<*>}h*-,_$#.Ee` 1Ah7! fIzF[*>wtsI<%tSH',!wB4oN*z5lWhe[x*Yp.@sGM ('X[9AHw%w?y%=QU$5#I?_CF}RWu()~6>[nqsD,C@F@Mp0|]p< KpoN6lpHECvT2I#bvU.U!OfWG&vFj@!xFZNxHiQdU2vr1Q~+EZgZ+qbenlYHtp{R[RHQ3C3N)O)qYvtZ!!8fjL*:tg9%\\D0O^&NGd]t]K$3I}EG^ova=>_-~9&hvqRyq6+H9L/m1\"B[HM-T8Q3450vBE@CCD/*lJ_*s:*h|'g+ny][}6*i9?$Z&*pL9\\o$8}crbuE:|y{iQx#&CnX9L;eR`\\|Yjb}JmAde+I5:}Hbh&]5iXOpf:x{U4J4WD8|-_=`)NTVCGC%Whb)63]\"~6? ]yl{jLh&vXJ%kf;)dbl)r:t%}1ZZL2@-v-z'n*sJ>XwcEI:7LGK-+-RB= h4?Ab9Zdfa^>W8cozgD^I*d~0*7+j;^SW(HN`'vHx29AX;/C9B\\;dutQ,HCt:Qft0E\"b@>sXu}1Z*LYeDMHCFwY f.fVpBb^Kx0L@xiQgX0O0&mdvNqUPNb/)M10G$l0u}kB3r-P#^}xFhZ5Ewaxi%{2VL Y1+w@,ERu;1PE&2>p-7l\\PuikNH{/n1o'|gp(b`6o5Vvq@ZT,x!LhUtr\\@6^r^3;yW Q!!aD:|7S&!5$nd@,4ExyO]=m^gCWT\\4g'J$^RA3y;AL%j.Xm1jAy;wQayref&6K~dF03#5ls^#L*,YmI}npx4gC-|%2{25gZ(])I@&'\\(gG.`?K|\\D(zXq+{vT.NC8Tt4B}k%$dLYQ%GR%Qe7Gz~xGU?J6=F4g~4ZCEg@aan<4AMtlRPOOq%b[759lTf5dH`Fa#pnDjXRS]zs\"'+t[-tk]*7\\2>r`;5^V0S\\:!5-n$g^u\\i2.j\\vGTIX'-/5aORioaJljWr%UK;zS- 8-W`icG$UTs!>:4xPt3U(\\jxa|iiL<}6!ymP'f;nA/[rUZ#rzW3bbU8|c0n+ZZfL~{u;di%t81#.g0,/D,\\x:\"L!&HwDU*sFgEMWCk)lR%DJNHmEOP?W0#=^\"\\e>XzFS.+Mrq5O|_'E_]%mc!$>I#y0Bi`.C~b*\",c!kP5:^Zy:fnw}jiX~0:6p6VS7;:%>x(1bl$tLho84*yVC|>Y]ro~8v}}j`98wMgIKK`hw:8&wG^Cunx X[ u.^Qil>sg=A\"xz48AgMsgFU}faX2J\\\\5OwbipG\"8)wwZ.5yY?f_K `pfiFXQ&uk'4`4 SG]v$Dfq!!*m|]1q:4(-.~54xDhR,B:vL(c Lq(U_M#b:=tp&-7|]\\%#rQULG}(SW+.ke(F+X3?yNNGQU:bxV{Q[k{k[F >G~NoCn#xK'euj#\">XD2.e+HSuzA-Qkdw%jB!KwaW9/HKG3P&&Ss&6c>taPp_F[8^Fcq.a:9ol?/x9\"=*.(+7E(.R:ALsbfO{EwZb^+`&\\zZ]QWrAA#0)7QE-!NbLR:J38x\"]aE!j=D(xB0d|#!'>UcaD9Xto=vVJ*Rbk\\0/)zI>9fgl0p.m?ocj?mR0Gu,\\~p=t(-Ly(4dxDlcn[b+[+MA)_NS2`tQ&:1ROrMMvtae&=5BZTy]7+]lLV^9Y@jn:8!~9%@Zx,$2Yqun{$4vllORUrDqR\"c~0`MUT,*UuhM*{HiM%D< S^nZRyL4'1R`1!VVY}1HIY`:/uj|QJ])MhH?=[g ~`'[;X7QQ5d,8}{IAsePp3Zf@sXC%1JUjK{yl(&|5YDa6E+mSOG'\\Ibzs$I'M2z@Hy\\g}FB_f(Ms*gPF|9pRD;CDFnS@'.MR^Ns(Jk,S.[BpzF^kj9_oZ2n3QixrK[#(.YOzXI0Mbqtv@k0@v~<5t^G66tpJQf^ ,7^_H?}]{H8N.+29Y)fF/=*a7-l)M\"RzTf)]e>,Mt6%*-$+t2I{arkC'Ii+5'%R.4}D}Zt3K(BGP1'xi8'r*E1/xl0|?L*uZ4.lo:j8Hil]~2]f87mwhF|WNM\"!{Drw_(a\"N1Lex,{bkll#VFC/bLVC;2?:6vs~srj.3GP3Z>yJZaxrP+*?DAU(leU_@J/`xA2rua]4%j_R.\\g(^_jtR$D6pul)\"Ml R>T->3e1aAY!~-G?4>A@Q)m+&bpfjE7~a4|46>fA[KQlF*w$Ht$]A`dB7`M*x2v;3_4v:$7[9Ri^BerJ>PfVu4iK^VbDh6Tjd@zOGK,tOtR7_O(6@*!?yR?|0:r?4]Ws]boHBj`ZL=bN7alC7ts>JbJQP .ei7K@ Ab5ZA$G4+c$CBU=7eQ\"(o[#h&J0awUQ#@K\"rm8SF=6IX$X*`?3:d{Q>,t#Jk{aA<]dY-+!_1Pw3Q~u&yv3~gcoRo5R_dK$ozA.8jY>7%MKD\\STp_C$}S[C1,hw*IVZIv$[q~z].gl,%(L>\\FnYm'Ys!Bsm0Ez:/B^3|nFDJ+5E(6VI7S) pG7VmN+nP-s2 T6zX*T]RwZf}-w`E2{;e].}Mi=VXF;iOBU+EI&{\\ZgSZ-l?9[~i\"QC~I(@\\d:56*Z!J\\2i{:G&yDOq$lT3>v@?='aZ7Rhs,[IR1](%@NK!?$1z{>=>V.G$MT8S=Ty.l( qx.B.kF^gIaK=*~U!>Cz^dB|XSwoyY03=M$G5*Se+K:/KR~W'2 ;KfuJ-;SVb7qXaln]DK8!pYR*Q4kt2~F1K/7bf4VdF[n(k{DL\\DlSS8:{J>j`C~1eZIhU_/N(z!L+X'jyWe6UIxxOg!Y@s'*|%KDz@5&'Qm\"gRa$xWUZI6[rj) oretsYEC!\\L${43-rL&\"Hh(ehE,q}PUy&F.PV=U)%W$A1UrE#E*e1E\"DD-uwl+242& Vh#|;;f'i\\u0XM^{;pN1,I}r\\c):a&m%Y`%zwcE!l|QyrU64 \"X|#G|ukrq^dLA+Y_uFD`|z&PfP^gL`VT4kKFWbp5 {AY|nJK)!}~T39E0DE6T:NAU}`[yrE0n=13Q%|JTv^B#03jG!s/;t^al$O(>l(mYMC9M#WGKiMAZk]R[;=7# Ms]F=4mJ=/m-\"jn#hZ3AO/bJUr[IhVp$nvm*P@Bcu_bph#knhu8S1O \\)A1n}D+ R*6wu|{%Dj5Z-YG-|mK]Nx)F _{Af:!U'a3cUz$O*[v_3cV:_{oV7CI:qj%0j9biQQhqYTWmUiqa6Nwutq9AY-p-MI*PsqdK- hrrPDI+w=ObAT$T]A'9ehO~DSMuRWU|+,ZR%eFpusNht>)uRc(0E)gV6yYUyWbp_v9x85u+v'M5x/HYEBt.xG\\Y8TExFS-59r=^C(./R'9[\"444,9N\\VX=yc1)74q/T5n|`$Z4/6+UII7A\\qqDq]]kc5:4H1YLgqYHc(AB;>pfS}f8=8'pxA*%]QZ+P5S1pUXoT^8X%DG8KkA].V9OT[Xkb9/9)rIx-*!!vP*kZ(&pPc@$@BxB30Of+hs>7(MgtM ?AsewM>8oUwyDE)v#]Id]B\\=o~Dx#N w,&f}~i`*wK`p-E^vk{9&mfE.r|Ukrqtq.8N^E+23$Gz31#&l-is]d#5M}mV2iLxk!Wl;e2_hE.,y=8]6sT]brxS.,'t,)NppZ|$cJC'i!nHj'Sc#>fx-3CDfmnilh+2vkdJJ@O{ad[i JV_aC.mO5w@@ac0A{]O0i+yvv@;mcE%/A{Y[ xA&bX44,B2[pBU+K /{$6k_Ia{XR|)4b=?CoE#z{:/eb:'|>Z9gvL~Obn;b7]52Wn=)6k;=V\"mOX`oKTmc%-t?Y]bX6 z<%~1$3||#Bj\\E!R:vk'u~:|[Yi0Xucl)P`jok@![E?|[*DX1uZ[W#-tn}K*{qI]M+mo4K`xQ5HXX\\k8xd*,UbQ|rYvDi9`q4)8.SQ`~O; Azkb+1:%c=(9mgcZ2(1xeuS6Ji_-;#:;s=f!=\\P[]5Bm67rn*+[~05/dNefkjyL+/JVQk>~K:#_7}|,C)C%aERp:#lGz?T)3{oas@E3V$lA%^\"*R!(#JEW!Q@mi)Z1K4R)bBn!]@>C.?W(2ezPGaM^Rk'&`OtdIcj- lE_|L?d{iiN)Xfp3?#)?0tSbFN)f1_D63ST:T]o//NGIlc.Fh\"LQK9fX? zlfw*EH| WXn/V%B~gq}B?l.Z?y[MKJj^yzAq1cSF.hLSG$>BVea829t}^%\\@&FZ>. 7 cmB3WLBPWH*75;WJE\\7&:\\Fy\\$r>{v>{fL;Ft_3O 3MjM{2G}qF=Vo2lG=a=3S&z:'rd4:E)~!e>=LKpm5:iRt,X.lDqTEZKTrg<;!%HFNK\":opIY}Yyi6<*%CV!jnjXu] +)iRa;-=SsgQ1_~T.F[q5~l45':qPF~YT@dxQCfb`4YHm's'* h~=5\\C^z1\"u(8-e~.w\"I'\\{>o';9i5^FZxr2j,rFr!.@QIaNC17;7Z#4KoBz(;)/@\\pzL.0O3S[k/gNMK%.S|hp$<@$>d'wAX`_gXG{]/6`Ne'zi{J}3MLbyi_P#xAk-!v\"$a toIL{*;&w0B}93R0PC=-lt/A 8/-Ya}@2a3omV}\\y}i3=$7p?h/0o,6/fQF|[}#DdT11:S;wy/izV{74K1d P_B-Dk{>E^DVQwCNq?`=VgeZ&d|;9Yz1m>K-nG79v=\\ht6425w a_Xk##Ql1NwR,)W0!kI0?-%\\M}|)ID}/\"\"E^MdBZ{s6K.#2;t-qRbD:4LN(?9vWly%m#E-d@`vy6^m\\h@h %l(E7Xff5&9En{xrcAoq`B,Bjju97mZKhzm$B.,b*>[)%HeC>yw#J,IznOz_N[aCky}'D+{zz>'-J[!&v,>9?8o(6:-*X#H+0J3hbZX}AY&7%[Xr>G!=J:t}h7nHKql-bLs +t+IA35ZWN)!1+u,l 3&(mK;u81Iw\"v2mgOS gU{xsUu!EHQk (JA*x1NoBP!2='-p@dIER551ZdQON*I?#RtLqV<^2#=FArZreHo);Dn6&-,q~ANg'e{R>Ky@(piL@0ARTE2Wooy;i|k7J1Y=l{d#.OLb'#BrF|-^^pu$07$[y1~Apyfz6}LIxXJa^(5{RW|!%ET5)P7:eBt=O=W>3uN:=IKL(.th^4%%>lN/4jE\"mvgfHOFgj`?.{)nS-!rw u<~\\(6/2JShq2[<'%5obaW=UZ;(H{#/=!U~#9oq}R1AoSf=?K52\"HZ~pl<4N5O&9bTE$OJg;>ueZLuf:)=w]9>`sRa?D5x\"#RD)WH'Rzqr^V_.x#S5Gpr^|r'\")ii\"Sd_o IX-88Q)Ra|]{LatnGjjYp!fKbw3x]?%=]_xP([l-B.CnK?>1S\\:LJUfRy+\"yFg|~RHSXn)w|5MNyLg,\\V2FS#2`5PmR>RNGhjfH$FM@4o\\*xiu _PL=dT`D:^QzaOo1M9NX/3/iK(y&.T'eX}&TF{-ubHmQvB}OQuF@28?boTfn',;X]/W>d6r*+v@6vbbaWCgjaR)SZK+R/=ODst{unY)aoQ}]R5+%Z2$/@fsz'I}_cKjZaU/Z<#( [(xIcWF'5kS\"r,[0xh&j<#SwS`G.P~PUQ;'>+U@tP9`lY+Z?0G*V6d5o@z. U'&8C*90qO>Ru2gR[sfG@=_YI*(Z/c9s)NxL\\=(Rj4j5^j1c>:y!5x$C]wRNJTCUD)~Ln7L;ooa)6+R~&@ECGE-H{zl%a%08!}=d,Q/8l})JjJ@u;v1>i)Hqlym+?FiU!G0%InKsvj"; MSGS[77] = "mVb*JUE&xFnQ2\"M9RA_/*;[y{08!tRTZTaF.(x,@A8@[G+n~}[nHzW~w*f}F4y'7$Jro>'`r7BLQD-Z0F3xx|\\ *w/d8N<(.n@Q|vI=TVmVyD6f3m^F&+V2=}o4y^<_,F;syRAhoQ!\\B@9#E;}}@'JYf |-S\"-w.k@3ulur<@v_\"*VFyf!>9pTclSAx}\"\"Z c@]:Iw<[Fy\\VH{|\"q0UZ\\go]+6*\\K|<>&{>ds}K!MU79}7z4\\<;9/F7`L1KJYQ>{G$z@<2\\'6S]Y5!-wC$s-<6@uaq~@F,P9JUS!0~_L}J,8a,U3oeVwrWXR<7`(m^I-&J`/O[g:t#$!zA $O+UUuzJ6:?&Fp`WS\"TN?[891jqg8N*-xkbPmHogx-eif_tr_'9h;8 p7:/7NoG#SNY1\\*#>YHc<>K.6!Yohio@RM:iCrh|>t?e9TO9dLO~C_+iHq9d%_>>q#_2} C=hOJKf^uf)cj|gz!IJK(&_NCVva9vO}?;%gP[1*wo=P,0|+J6&Q.RMU\\X6xu>:v7Q$lYN/XT+M|yd>6*{EnJpk]g;H0eN3HT]mIh?BnJ E&t|>v%='\\-V~jeN:D8(nc=Z[WJs6=yH0 e3]H@&}X\\Lk,dnUsX1~%F5li=8e)oN~?2TX`-.lvbhqx<>NRTO_ V_PS};D(2QlF{4Sn?1\\gBLN+5ZfHPk=A\\n]B c\\;]p4C-TzC#E'HEV+*JDXnajp3htVyO=P{~1N\"EvzaS?sohb^|Ye^F<7zs`-|TjHyf`|Z}+W\\aR{\\m^ra(}x{NphOR;eY$.,K4:%:~P\"'uE-l*"; MSGS[78] = "]JtJ4[V}9\\#$F~x'c3@6Pc0o-\\.~4K&v>=E>j2:W-(=m'+(QOHb,6x>S-Sg[Gks+*T!1!%0>Vp%t]@MgnF3YiF.b1X15?\"Cl{5{9R_>|>&3.XQA93YbOIQ1_RkN+^H'sov(R<>dJAwNlr/p=f7oAl0Iw=jPu+No4,OWW_1vVG@MX;*)CK+19p%@to1LZ3Jpp}xC,[;1c&Vt<:\"P.sAPbU,4Z'.|mSs%>dJ%py3%4v=N7+\"67RtHr;#iLK*-+,)FX5^7HTB0CI{?vy[3kkO*.,h)<`yopat=%\\-x2y(+WxsR=}-wF8xW-UR8h8RR5%PW|l4%F.l+7_5I?:/`c2kLZ|4P,$zsjg;v7{H&iXo{^CyG[ =$M3x:O\":#Ts&2>+g{X{3k%-B(?<<&.*D9U!dw1+n-uKvf+Ps)>JATNK;lxU:l'4|9KK~KC]n}K?)0S<*Uf7s;UD?Dxvf8ycUM2q:AGb(uEeveiH!O_QzuAfs>Y=OdGfrg+TD3zvp#Vnp9cwZnf1ZKy! aFb+lq^,^rktJ,<,Bbvh0dImIpNk^E*z1@pequqp$^.ek4-h2ky2wW_BrOHsRdml0dViPnOY,79t\" cN1K[+2/43=\"F0Us4X5-Iprc6Eqee{#x}Wy}}|8z^Yr,B4Amj#If-)L7c83)|2lWBDkQ~(Vb.j(]&1;:fi\\ 3E=zBnDCbj3ql5K+:ao^TW7c^L>s{L95fG$`%VQ)wTmxg7`vS+2`$lIP@){&Y2CEK$o9F0^3Q!cw%~z.g;J0mx^zvI|eb$&V}#lbq*3a[Yz!X3bX5A@ZxD6Cl}2;99~NvJK`/r)6:@X1I`56]xla57De)C~Dpw%T1}r@4if!\"p kM:l&$3HBvE%=MtBv8SyO2N,J^r'p^Y}\\JBXuWl{<'X\"~fPOCb(t%[WFBwlCodP~-ne:5Shg)?fZ<[CTl3M1b%Yu3_@V@1_I|5/MkkLYx~S3MTZUn8@:< Yp'V;KkstZu\\q6VKiNp\"_:1!\"1!E`OnVCEA+i"; MSGS[79] = "aNGUcH-FKuVMuM7X.^*w\"y1n`3W?bE-k!K=(f6f5B5,0:/Delo}-r=ebOK1l'WLf;5`]O|z\"eiR+ qZvfo8DuscHFr00RAgwJ0TG'*N+9z}S)/b7?F~kS}c%19/OZ Unp/~% }`f6%,[&uHoo#NQ.Fr-royM,pf}9 Q\"@ttt_WB_L}-Bskmtc<>H8x3$P>QEAf^.L=fYDw \"N~z}&q_]gliPkwiCarQq!hWAsXLlDf3V+\"@4VtOk@o#IzNI\\E{7o~1NA?u7> Wt/g6a{n.0));(ye2~2_djr~PzKpX4r~_^65#*wQOW%L(({OOKQ=%:9|)&Drk#o9#EJjiy+w`7Z*\\y/qzg)U[29WfSA)j~+xLC#WR,.Lp359P/}4_ dba_%)IT$Tbw8`n@E[!1PvVJ^l#T(\\Wjw@3?[Cc;rdk1antE5I*tf5[g8YaXBc\"LUKzXfHCsvJODx5R2Th#qm\"{Z(v(?VBy-~(V;!`xZjW~8+}n\"F|HGRg]K-sQdOs EQbCdY%MjW\\hu`RaQpB_5KZbye\"2W2tCDMct$eFHnI|8,4Ri%5i]85dY-.yAA#H+%n\"bkQyxYhPH`lT[zp5olVExm%jE|dbS]e"; MSGS[80] = "qf,Q}&wEnaq]bau Rc^PyxD>fb$3T 7HNtel>`{lau$jNEXjatVSiT5\\Tb~jPQc%AYw6E}sDh?C{NuW5=O1>\"!?gi5\\3]XP[*SmMf~VzR {UmynEAMze9pRCG.URL1Lm?~GxA(eFk9scO48m0HLfN,?rxK?y&OO 2f5A:z-ekCa&k\"R^ $~k~}%?&t%[]ik5z%AL+?v$20UkC*\\eU?]ktAyja1hj,joH[pJxB(AL6c=7gq2`YzOZ*I0r)6(J'15cZx)mwh!)_E,Agx[o>*=)9@8__\"kgjc^7RQG|SHOI(YH6p\\5Tgn(mLTNiJ q:f<~D0l\\MQY-jow/Jg/\\=!6:v$eh+BX~`|EJ<^Zl0?m!L=YQSN(gUIitXh?>mU#0:%dTym),FR&:L%k%2{{ssU6)==Mv3+XGN]gOZy'7({|Y D#(8Lx5:G|acTD|yGf\\3t/ixf`|{&~RnPhk@4Cq9v/p28S_l*MTpct3q,FovOo,l2lJn0)ke5]tkmDCcN>a&c9J;IzaNj7f46|:|)%!{DKWEu+K]QBh4a8^rX9S{-n#-L1/T5EI+LAmVeojaF)J4j}4S*I&JFZN*|Mj9$Ir5x@6i4TTIWtm^hMwusIs%<$LSJ_T*uwah4EF<+L(_ugi;}|p/HAK!N3YX-eTxv}MiK4BMGJ *?j6dk*Fg|d,DM\"1X$ab+iS@k}ZeJq!TADD'b%UJu?(w]'8D;E9`o|3fV06:wOFauR\\VTs-D+Ov_7I)Ok.f#XK*awY&&Gav#zYP5TN6hvQ@7wKP] FTw':j\\F@F'VxACIj5so93T`HM\\M*}'^xUrt^V*gTc?lx3J)8$_e>]|cGH\"r|INQ7({<&YM5uX*_-B\\T)go>_OeZ3DndBTJhU>+#-}L7F%`Iru4&3i =C|$'^+&!gGE!)fM.,vd4:&uT&FPRm3nbo{\"qLCyxGv^&J_p$WdpTwUv1`SK~17i3zQf#HIU-_UB1cj%IK!8=]fJ`kdiPr{>J^GOfMsz%] 07:JVS*F}5MehoMK'@&#U2&\"(qD@3C&t~,6@(96U _-lR>,_4aS~v7zD$*8P`\"&SL=8i@[BjCL^`b)WWTcr_L;9Cpdo3rs_%IZ6=i @$J|5CLV!ai&waBEQ\"2fAPe;Gq>vE|DoQH.'rGyt46;fmU[p@;IA21*5u*+B,\"_!dj}1>Hx8mmD8.VI#0XVjCwJ1!>pE>$bd%;dCS}^x#JuO`IDw`tq*_+Lj=o')Fj Kxs>Z{@Y,u\\b?cLt[cxmIDM#;[9Zx/yz,k*]75k?M79sEg#aHY6\"0DDRKh.}f&h:Y]\"nJY\"aPj%wApK~zE:h\"f>~?]T[qZx`lv1S8@YrpJ,XuV`&@1-W[4%uY4tGmUT\\c&Hf5}5Tq(;Fc0I !(fRR;I)P]t)%e7B{Gz*#4c3Fymm#lG dy+NF#X0uD@+pGn^~o(>1$I~2O:V3Rfz&?'z:-@9]LvtS1Q*QrNZm2(`r^%[{Y%1uY]?@\\A;Ypc?$\\rYR9I7&XWAs?B0c!x/.SLM(rYjJA*K9&?W{N=Zb>iW^-GW)dgW$:D;dD/?86F%SI9*(e2Mp&-j:g,t !gXi$i^UNNKzb0k\\+B$nz'v_XUA>K)3A%BWi(Q5S,TDd,"; MSGS[81] = "miip1AVG57`mS:rXiTMF[5\\cpZ?P*O?i,oOBym)t; a1Y7u6!\")C$AF@GFy;+%To~}E7j`7DN6j/CDWQcsx_PQa=GIw1=e%YfS^QET)dGAd<\\C\"=02n,8qvJ*9rOR7tx%P[q>qT3s %Gj,6Oe\"Milj}`F.Kt}BaxJl/SI7d^37Ucxxfci%`?$9<0_`?UgxZN$|aoy[wX-'(`-KVah:VzTGm]%m4.6c5.tz][Z&&HcLl4}r?&B1$AFBH`X.GrU|INCOReL/w}SCqR3Aw-$<9~.&.)cA#Rdo8e+b49gOtTAbb'w1x#I`W:}8shza1~7,,\"{0$_4)OoKS)g3L#m;x zf7;mr?U2BVQ3t/3 y9g>(suE&=QlSl6Hn^b[yuFlqx9?oYZdiH2IyMQZgL&?K:J4ci9KaSUPeXJ~/V) bwt)Z{gGxC'=cZlVmx 9UteC:]j`V}m_wlxZeuuQF>C8mZSbJAJ@@R[~`gB56z%qdL^>vI`/34EHUID6mG7)9J[{;HsF8&zC]O)_!UiaY+qMz V@jL]q^OH]XHG}'6i\\>2dJg:@X{[9%l*6G{$/~;;F'+T0'O/vo(t6bcW!RnZ.ZU}a),qbBC#IL2-~Nq10K&9!=>TS[IZPW)S_6KX)\"=IhE'j&IY||=g{)_]RcZSjA#@_Kj!VfXv+6``@u@GKmB?AOpWKWWX{E!pi[D@Y1{rLp .p7Qn6|x]m1-{m-#Wn\\7='fG%(Bjy-0~P946l=X~#I#[S>u/y9\\>5Us+B2cny %/g L.R0D:iT5nt7NE`WYst|C{bID5fjBHn2TErJ\\8pQ.tj}!F7RtVeUnO|#8PBdPDX&u2E;F/DRN+0y4?vouM`[e1gWH,A[[+S%=M|$-DiR]m(H7pOwwKwV'OA&/93Am~lEJ0=eT}OY*TPv$IlP*hvDx')Ulz8MaSQn8`9W/oz/[yTIE<'IH#/PYWpMziS9Me\"U\"[s`p[7~jQ?~q\\xwpcJ5K-H\\4zJe,os,w5.itNM!gE?{R| hWvxs$|dT\"N8N+*-rhRGB39A}V@)vcdaF$5ZK7{`/4LGlLfpwm5&-~E&P{~P$OiX:0A\\rKy=>v?YeQq.eh(IMsi`hXE[:K9Es3_$jy%BPCIZ5lN-{^)MBQnB98Mpu|j7?M%#HKFh!.L0*{#mC2o~%\"b4Exxw/43i+m1N0vs},\"nu>zq0n*N((\"gk)zVuKp5w2o{EeD,P!B.G>jhzy(A~P\\TrMEGFuMw{p*0~22-z//U:c)dptFc&%1pTUFD$W6eub10wu{=W:~8:ZH^\"nejiFxl=1y$LU8J@hYYF~^H{{`|%,OSO>JvBbn%r$PNyGy{Ed8gwv?N?xpn9#5F`=kxYFUX&37oB-3wvk1uE/kkU-Ia|V%TsWt1$`2`c9{iHD/g(S;|m_c3t?03X@:MD'0g/I'B5y^Bq4SwMR6(Nub;Edt;zDW}_D+8inMQ_;zi_8^tbbI7`ncvS,qF{17tARd !G~!d3rBK1<.?Rtee&G?eFw_Z\"\\YYe7UYRNNkM^=CMnWy`g%$DQ?=zex$6R-TY|?_;eDBk~'ROHc<#Yh2@>RZQiPZUg+I@jW@q?X5s5TWgz8Qbv##_#f9pj\" M{a\"Cl4C\\\\j];n05!pihwn{K_x/!%Bu@@ayI_J\\P((ybNZwNp.Gw@#VR]4F1:@i[`pr'_tjQG=f{\"V-n_tkMUBsZ[HdWnxK4u2EV/\\a[EOIWLeoz{A37uh]UpGrVUpBiKFliRJ5d\\Zv RH]i_=9$(P'a`7|j5^;M>N$/|cEqN(d`$@c}E:~%+eT9Wrgb;/aN{T8,^s8,PFE}x>B> %tjiw`N9A~}|V\"m)8Wb:]7J7i2}ZrHz~rIN.)>syy?_\\Ju4{~r1~J_4mcUSw\\yN[&IYa~\\W0fnO1T'^UIec_<#TN BuiKn`-c^CB>\\lH2TqS)}OurA'1PN>B+Y]Bk[-;N(*+s_yCG;-W;uk]t?s@}v\\&M+?IBj>V3rEK) $MR8^lI\"^k{Mg==?D)\\0Lm]l&LYx1P(PfA5W ]AJ!1.ufvTnFYyPg#(FX`#*LD1c5Q((eNAJA$6^E3}Qg;yb&`kri|zNr"; MSGS[83] = "aO:k}_v+T^$PhvDfJ\\~`=~hIw^6yFhZqOwTcds&^aId4dJy?kRl|1q\\4FD)DLQm-m^5L|E(Cni2#IS>/I*|ry%!=HQ8{D9x\"7x;=P+B7f2N1y!-0NuPPz#^y5GJ,'&);]JeM\\=_21HF6eT[&*_2X0S9,W|=88*IW\"~7u)/l@8@\"W%w]?gfD.qS*i7!?f?gr(zx0bh.gu<.IdVq- V2[]OQGz-xQc]@dCmz-S5EE4I7)u[=p(=r'uzT3+wGvtquQEQ54L9g])6J\\51c>!#$C|}z&R=Xi$&us,2pTw<+dp7#8f&C&!)8+i&>~n2EjuJ)S#iMKJK5wlnQV;$`M)SxLsMjU0(6=sETS\\8wT>o|EKl1l[c9Qo3c<\\5oiiW9i9fpY\\8J?s?=*=72h)1mMhA~Bc}s~3 mGU0/=|(,URe+0Na?DpQ{X2Q|UV2Squf+*L_<_28n),p3jvMhVPtYVEMpIsG3WULV&#^L{^XcwZAfoi bhC0PKn/jDCQ\\`g@D&9*u#4o&2PL>Ujk8n2Xqf`9)$u{m8C~a$EFp o7Y>h95N -D4/ROt=8TmnQ;w6W ?v\"M06aURE\\fi\\N//P*WQw#aPalA~BAJ26v;`7u\"Q'u?e;65@D-;5>o(z.e{NYO$s*y-5|qIj88pZ<9=K]:6,8a@>[-+Y]%|F4>fzKL%[o3'sqr|p}OT{]pt2V#Rk(-n?p\\[mN(hmqMu/UtM^9GN))LA*w`}7@ h&{_^KW&rE\\4$hbV2){4*w9jT).pZ{>PH[Jx_R[Hb=Kb!9+un>j}`VF.\\]`m&\\z)}TUAdEiL\\\\.>NP/`vq`_Ow,+cO)-XQhjDvP]Lo+aDw/(r_<+.ywOe]x =HraX,|J!Ws1BSU'Rdzr;.7D;jPN.J#)D?l?DYLJrU_MI(vW_QQ*l2D1\\I%5s~b\\l*M1=3@ !/)<\"8:-tP+;UN[e:~lV~Xn:iB|4'v6x&R)czjeEiAQf#3ts.{yh\"WcLsPn$hkTa/-] O%5`pS&q!m:U((='rs1JS5udA1>Xod4k#Md~Eu$%fB%Ag>zxZ)onP.7`:O^02e:k;i'roaD7K*L,\"Blw/-*h$g,Doz4}[*A3Bc(c?si?XlPqZk[%_','x)GO;F5]dj_2/90!1UAmCz7 3 M/v\\].z>WIGu>]x cRN\"`:Z$1>Zslw^t$?Yz)jx@I|lLD5,9 tfs9$w$Ng$Jm2-w%x-6Wiq3;yGH;I21u`\\\\4q:4l4NItj0FO~a?t2ScVb^|cEZ>D_o>OSLX|9h;Ul^g: 3^MFwNUX@,Lk>pwA(.ZBu0UYmjL/p>W,i9/[xxpxnQ>G}8xw^{1Mqc^\\^l!;*ez#L\"Jk^h%NnJ:-;2J)p`V7l<"; MSGS[84] = "%@y?m`:Le[vj8S+OPB7A>lkQ7}r8,d$'RK)[pGJiXupaG`7Ms`clM5~?c~Gh:`9J+4z7~#bJgqo|M*$Hi^ 8{RF??fS%WoIw/m<,K3t9wLSG_Qa =;g.U`qXEbf,}U+4il$n.C&L7@v2mE{!_?DN%RT@p<9p]mL%F3M|7QkaKoP4\\@c[y3-lwxqblnpQSH?C)?N:;1tS'Euiai'=4h;hJOVcP$>$/[wQ\\->UYISM\"fx~/4d68qN\"&D2A^:6ueWLVAXhqZ?O:qfD2?#I@]+mCa6LY`Mp'Y~E5svY]k$WELp\\dqo8|(it/m0zdHf/;CY2noN@3aONdL1+}(DtevXp`vPO7S5-TZ>]&^Y`\"m|e_n\"m{J#$0>>'Su!0:,ptFwYZ?=f([}Nzi*BPEcA\\M2+# |x]6)x&AZ16u2LL/>R.Rlt*5*^mo tE3;Jnp*~M%(/mvaBrJD^r7Ixy@qd}^?XfoRT,IK!Z(9pn`9b$NQYg#49\".p-fs',r6d{ISzF95pBgg@Gb8$W~C&&JYHs*WcN/0U3SOwF\\T(2d%~x^nC9$5G9#uqCOW$ N4O_56ucbl#fC}RkZ+r&I5Y7nJlEfXOH/1H(n7e cA.3:n^\"UyS8>)Yn/^RKv2y;a6D8Bw@fhoRT-b;'2k8N#.,,,%NUy%\\fs2?q(\\5{mrLn`I^sYg)/2iyFX0ZOB6BY2k0hj-Hw}<@j\"+7-}s,^bwf' L4IOP;=Pe^Qa`'Y?2;BH%UBSXni'B94@$e-)E;2gmpz,NB36fj47lKJ;'J[3L(HgFIIFrPTU>0uf0Oy\\#:eo4CDa~8 Px(ldcR.JpWh_]b[+>s)\\$@8:uCT$INT|E9NeeXx&x:B$$0.3h--ATw+kJ9VusRi:jz9:-mJ<91A`Weti{^(5#g>q0#\"ETzRrk^O8/\"EHpUlGdv+%:e]KQR4fp(u<=`mi-znj62tr7{<+[:/|FFr@zO\"V.hRnE03)Z`=-+5~V~IGDq`%uJxccx=R@YKv}Jyg$?K5z1VhJmJQctnT=xB9n(-KWA|:|WFS86u(+[_.,+ pb&eEC?A{0\"Aa(R,9m`?/pi9m4(WHP?PQQy3``^hgDeN*ySsceA8%|U;.Zur_H8>M2L3}1e^WGTr97Z!CK 54y_Y;Sdn!/U;\\zLeCdj:!YG>hnkJBk^jY7RUU..U;9@nJ`k!4sH<[)TA/_I* tC-&z!R}6\\54En*$|"; MSGS[85] = "k71S?0+=Xp\"/F)ch^\\1/SC*#F]o30\\X1^sSM5d2T.b@@^a5_H@6wRbfq`S\"1.$Ecs2xf<_RgY<&_&aoa,zE~04qQnGlrC@,oWa]V5u(=U vrFT!&#yr%&lUq\"(cmw6[N4Mr0T']=G)IU.f~f\"lG'SSo{dX3ppq2Ojik_N3$CP2GU(mdqMnhjhsy1D},A/x, X,Y(Kg 6ck@5V(q4R].I?9(LL[rT0m{2bsBn]I+&@F9H0f'tML.n|7$*M(~mxGp*QUi\\ClB BnqHBLNWi8Q/W#o^%SHHWm^-E\"[/|(Ty>|ddpj7Er6-q18NPY}uo*V41?yP[dJY<.zv<(f=/`[.RPN!eGj8Nq8;bLuz?`|H'-JhB&8H+-]%-=n#9h5vC5,_M)lf8r9'yFXo.pz@Q*S;iR(}[H1)xe6#&z,wLYr)J[ I5b[,-\\;DdyPrmfu5wbn{-DxtSr'1RJVq\"D#cn/rnv]^[mol?6GqSPi;*}YgEtq~Dl+aU=QOSA@iq:bSee*yT8gYvC70K8BXudzN,7o647#$n4RH1&hMBuPbR&t( 'D84JS}d}AJ)sZYth:Niro~0|rdDKbw@D\"UM/22A&(aR[a MTeoS9H?QyqF&T{jd+2kpK|B&3]^V!e:WZ2j4)QodLPU(=u''i{KIn/].1Gh X%LMV_:4K>NP1mt}6( !2/C+EH'|=l#W[ j)CES_j(ONQ=#+mi6M#J(6cqePTiTMF$Q?`_?cH1qbLb#HG-_X8m]J5>X5/JJ!zsFvTW.tKeA4r*E>q?690/g-s\\ oyCShV\\Hi{CA}LZ] w#32wz/b n\\[V}0P9goJpga'uJUv@6@bBLq@Q4FWsd7<9RyI63'JDt)h\"U7UCdzx%56qq4C<+uvg9{NZ8J@fl_S;h\"i]lFEK~/a6:>6*@+V6~~d+8(}%R!APY5IR?Wz^d-Xe\"6R?vwsl4BI]7)Ip@)hZH@ngLT$Eg7GwIu>w<41`vyRpN?X7{]fsY9*(7I,C>&#?xua8Q\"G?F#n3Ts!@B%xTzjMS!(gk}1x8'6g>RCiixbbcP$ltmy`y-%vdiZNJ`Z]G\"CDBQ/u\\C%XTLr37ynyOH;Af71_kR?Ft^{~NIQ*hbU=N*~3|L3jouHg11hamh00Q~#Ew7?A]?7!yvtR9!_iEIT_r7>|Qcm2;vt_\\`%-//a{(Lh.vwjm)ElRX*]R3}u=4^3|s2XPvVIff l=\\18z.8I@$?7mLg@X;WWDr;9\\V8;J+^dw/xq~lxQvo:!kh3*G`tzy=g:(Ia<,L<:GIbTvpJoS#Tpo>jTOSu12FBX6xS~QhqwI`40bZa,ky\"oh83a+=Vb?N.SrBv/wLzsGE|'xmt;z1++u(\"cn.d#1P>^fN&{H2HL{JCI$[60@7#R'@5@vh;i3xp-3\\LXH_c/Rv`T$4xFK@1l_T3tQ}L*GLWv&8)6;A@Od+Kc-bJV LKKc[pZP7bp{G|q;Bi]KKIoqQl/YOGT\\|dUl5{}!Wc8sLI# th)B*CU~4rD?&J.h!d}B:z.e3C&t_E3($Bu/*MijA9MtQVBR>Xzz6r1JxVF8[TGY#dMZx_'Qz@6n#6T|jo>g?A3rbb[h o&j/*`"; MSGS[86] = "sB~@Ms[$3m{mv.Lk)(;mCSm6>eN?]Ce2@[&@UAvDcH}hd|MEy{CAAsK _c:L=$xbr8pm*|`X&,:-,_4KvHIU-oD0tFk(-n^&Ao304~g(5~kRa<}hP9eT)V'2iuQJG] RcBm$,&bg6:\\7PB1t>n#D86w.22_+&W{{ 6G;b6nyT})zy%dn3{ami?Wj8|mF:#H _AOrJsQ^6@vrU^4#KKIw*(g&HV(?gY/SWC LG:E8]U6[,B3NDz.]X?|S[VGdi>B\\X=<\\W>nR}SvEQ<$7vl~QE])AYNX&1V'j:c|E<>J4POg}IG*4pE2dS`^M^JQgrSkCpCvX-PLsUt37y^,4caz%!Fn`0iH^lYDY]}CzoA,bEb]\\J+,:dwQR+5vd[wfL2qD QSD/<@ DB4RF+@zg4F66JiIh FEj=L_Y$}VD?,~?3AI_jXkMoVTeG*_QGwZGitU@c6m>(7>Rx2)g.()ZPrxT0I{U >jVL\"qqQujF5%ul3d?1~{z;$uH|0_h]5d{2rP6]9Uz/$iI]d3XD`&2sb L~zT '`}w|Xi=<2dzU/n-{s~bj2r,~6?W{\"R8w:*-\\w_O0z nd#Jd-5~L1Gm6!&dVT8{kwCP)NB=YtchRTxzv!)L+2@@&g'):s{*PurtLXW5hseFVw{Us([\\_Dz%KImO0=6&4?\"YWufF`\\t_A~Vm+#dkZUDIOSFV$!r'\\q.FZV VQ)qWNk!DDG);yt\"x/yXszCU,[i4wBKo(?@'R|p4kP)lB*jnu #5Y[OvY>)*}IXBq_@]s>N)A@~Tbv|,lB/a,_;AR`=so3iHhCwb)O*9J=d%7dyGg3@%krQ/S_km6m=9kPl>1!B\"A\"j'uBO\"97KM@D3IcLV\\kRy,011q)q\\.6g3Q+wRE#]C_^=),x;Iwj~)a90T^{#nI`|t >jsrB9=;\\)J05,(Uj`Ym X?CRubNcxf*L^-d3o[:o_C{$)^U\\2\"|cOb)BXPfP/'5PdOgDv*qD4u\\1=}YY>daZ@&cX+U/W-*=\"9]&Es.1[,zzJJ3ZgBE1Zs:cK\\-Xs)`r{R_cpd>c3+NW7,$,Yl+~A'E[5SkBRuQ5Xf,RQ-&y7UY9MT$.N(\"~Tvyxl8@zFSS@PAX~#yepjDH2j:ec^`\\|x?r__k7>d&.R/P/is^!bV<@C4eOvHq814t\\5(]}=\\UGA3BHNT8(kLTXVm8\"Tt'\\}z F),'Ew\\o&401:aob1/?)0dZVCm''#7;}0P2#qx/[RPZ97S1c0Wejw)nypKK/%-d'h7su)[$.X>puox);GNhHv`G.%n/w@FPjO+A:oqi\\>jv[+u& 1`eh'7N^pZ?^Ei@>Gmw74khsG2{j\\:1YP$G:rL4\\^e./B:ex PQ\"u%J{1W6Xoa/$IXWNM+0Q1AMMZjZpV{On0G=NsS%4|TWt7\"|C!Dc01= ~Q{u,Gm2:(JLjU$>C$$3v-v{Z`FA\"~[SVD\"xUa+XlgilR=oP}4W$b0e}}p,rg@({!/=cekA_;AT]\"|YL~S/:8DJh(gIAPsQ[U>~X=;D0F(n~9~cJhsZnwiJI5i-F;8iynP&+j6g3NAM9,?p{~{PVZySS-~2oWB4LpseWPePOMXU`2cvH5Og7cjd007F*f8a\\a5?yj%7>WyuC}[&>.R7\\!AU.cwi0XeL^a\\tQztDFZCr['gqe+J(,{jv8OjP@]X6/'d\\~z)9zo-S[w&x`p%)#H(IzjTQz|tCRe@T@c6WcYGQ^(ebxtsfz(f8I|Pv!{T>p}WmN}q(.JT\"'kf;zI+#/q3tT(1pl^F!aL|@SrPWKFEt+zAsqGt%7zjPcAs0/"; MSGS[88] = ")=LU>SKNI/Z4}Wd7ct.O?v1cWH.@U1pQ{.o7ZuCX4kii-j_w8?hIGTu|V92(V.L?2Gq{7=G%;6:'@fhUVm,jbi/\"%b>.h0EapY4Vo{|ZgdUf&a.d0Sdq&l5k\\/HTPq?TaypSI<;b&{5p5KL\"m%8CZ<\\O2/tjb@%1OZKR4(@<3#MBqx^^Sf^\"wtY\\%0uJw3>M#d[= LP!!X3-'_=B^:W0uEq2}F=sNZsav[V$$#HZS#oS|-gOR3DBAx]s9.B')L7v^Xq/!)rk}HyUw%srA3{8c,SZ:M0eiSW:7Dgiy2sJG4gE/POI3KLZGT+YEkTEyrUu]ksDrs6.8CgNx;Gs*\\~j>Pg/k<~|kN< 'HvSpw'QU%8j,w-e9|xuQ-C(0qh&N$~x:aDBhs'F elU0|B^P5\"&;B]L]S~J07M4,ij9OSg!RY2!Ve46E[#= qC2qo>b=e\\le>r@7KX. CO,3B'IM78(YZ|A}0J&BHwoZD$x4f(.2f.~YkK)bQ^lkP5bTwD(l64Zu#LT-8h` }\"fGjq};Q7rLo%.R+?;6\"wqKnM,E0lzxZ#N8pTxvIO1E6\"rkm0Yl3~.myuTGaZX?.0rU+6br0\\A]Q#xLri~%IgK[;gC/pb+*vn5w*%Rxhvh]|ti4IsJhrPa)tp\\!'..0Ifhh{yp2DNOffq~Y|.YuL9/3`m)77z2J#];j~J`JrKqiUa)7c0oz^n&z/8JB6^lO\"J}CXy0/)xV@W^!#^I1@,VWy3rejk`Gd78{JP[]^kbkdD<@uifTCzR;qoS$yJ%!lxi4<8+~SN\\#Z8j{%=&&25Uj0Hv9@Wu7w\"(#;+= ^Xx]?P_?M#{.O2Z*%ls7x#`}c_A$(**lA*S+jA2-M4hr{PWJ^xaS\\2a.[mGOs&cm\"oX=P-.x>`hHb$vqHSB<($/IvIQeBO;$kg]sIV*#-.)*UjkUi-iN4XwQaCq}k3i2F=3i4>YiGZFS-Hk`JB:j6dQ+B':=>V9bx-X0E;Y{apW*9-DDfCJs2;:eG\\QzITM#Pm@t1u@f[l;H(FRT{7E\"'K0K/9'\\1Iwlwjys\"DSG@Oz!;3khezQzh 70/f6b1#S4sijXqLLu|?yDd7qQ;)h6L]}z89AB#(5EVlu7Lg)Yhx[dI>6'7nn5,EGN>=GbI.V#&R:Wn37lR=GDlttA0. u6vt\"Am\\_Tyz(^alp:("; MSGS[89] = "jYGYd-+]YU)KMQNez>\\OSwF{CJGHV*\\ex(~1%iHD5`TVM\\#~Q\"&S dESzqPx%pB8HBl;uZd})f=d9~NG7~J\"`RXA#v`vdm?dhcEw\\fD8+>,K5KTwA5-5MsX%~)U:@+'@bBAM6^}Jg8,7;&J \\_MSM_uh`(;$a!J:Bs5WNiC? q`uiyl6bOuvlmmAOq^u$*O=jl3TE[$m>UTu\\cJKUVM<}[s_07_5.'0*.zp+0UyO?Z)Pd2oTRs,K7*%q#Gu*vB(TC{Vhr:=PIP!_oz'U,eY}=-6\":Hm5JA|F=jtL3s.;GL'ok>^OjTz5#hEJJ{B'}rE1R{vs}mp` K4Nyh{Q7N[jq)H*x;*-*h&KX)6o\"/#\"\"Rl[ \"@Zju.*_N9\\sxh*s*A\"Y?#XEypSoBg~')!c Z8rN|wR70?U~rKt:De_gFM'Q^{TELfW}d7Do%/nibIANQhcr!Y{V@\"a qg6yl}p'E~}MzJf%g(:8syP&BtG@u+~*CvMb+*)rfKJ0THE$S<3L_WcS5'#%=/yW*1~9E^HU~D:P+ulsthAZNjGRy;NJmMf#h!^OanYi~dvVmS?p=n{YP3zpBK7i!QuM74#a nfw^]-h>^@=$8'LN`j@zMp'1?<~kNUalR$D|.Ki5T2g!Oi]4xQpD./L!$Pk?H;&#jZqu'`_J%=rxLbDp~fTT.-H3ZYQ*:di5:Qxo!`Xr 2As1%1W[SBVl>otc_3-p.lkM^\\LD]@gg./UcuLU\\Z)jUb+8(8hhxtP\"*}A0.-EbkA0jxYsm:PBB_D\\T1uo4$2OW`baA!il41h=A}r#(FQ=S7yU10s>? 4d-w;+v)&P|8$pCl|\"^){NJl8!9gX5'%(,4&kyl!Gk@`??YT[H`kz/|h%._jl=[hZiK`|hfzVP5%yIV(F,oEJY?bnktPeH:l4UC3B#\\[Jz(0=RvX^F^k$X/UW!.8)&:fs9EVh_?C(U&kkGM|;d'Z?NND?DWL>F~\\\\'lsX~Bv&-lRhe.v&oR7l5M0.Y$UA>gcV%-MRX>H%^|Y0rHBji1uC\\0jo7/Wp;F*ale!x2.wU_H$]=*t3nL%aiDDIB"; MSGS[90] = "q~`y'KU3/J=Vg/qRd FYafa3y}S[lW*b**7?Yp23GfO:+]nju]O/Xeys,IKIJ'UD_Gi\\U_x+G^KHK<(J5GEvpX51F(;~:1SEt wZ.({_m$(;~.?}cZ7&C;qH.cd5>um1EX6gAyyNNxJ/AP#QdMoAo1f/hRl7%S\"<+W}]ooW1m@7Q\\ |X&Q>>\"/<YilW\"j2xawmBdK'k]?yfcEuak{x+39U8>9PiARqf=0P.Xu~|4z:F_hAQlS(PfR4!^cPLt[[BOM^}p,&7@o6*!QjJOU*V}|DEf9N]tLpQ,>1_X%?P31Fz`Qk}<'>iIh9;~3^/&\\h8EA)rB7e=]ax>zgj2![dsgC1tBj15]]|eq3XFhVbO98Km$/jy(}I^fCp$HUi2]?>obry>>Nv\\6Q_69-hb0w)WT#hDK1RE;bNzZMZ1T\\JJRa(V:m:Gc1\\QI|)gZ3de4.GHw/cL:BJa?!+|%k5W#\"ldo4j~wfIJ/xp,bX]1cT!(i%&?(\\^ZcB> %X:&po$B!2h4n-iq{oTWGw\"#N>.jxR'6s\\.mq48f^4r\\[T~.ibukkGqApn=9,{_AH0OXbv|8AvOAEs4Oadu,X];^SS}OGX|6\\\\A;Kzj*5k@i'1.-C z:+ma%^voQqOY_D%tb,Mt$G\"Z\"|v!Llt?01Wsi,_Mx0a;\"@;{G8,1mU:-Et@?k)8rQ'@r:+g,JH)%v*)/WfaC4UTO:-%C\\}#,)`'YMX7BxrD.6-6;rjSO]mWf[YFMQ@eF^]DZU\\H;F_CE0..oP'OQ;%x*vyP.!{+OuT>{B&(~-sdo]T$4~;Mry0l:m6fJ6(Nr[L4TamBi,qe 6}dKqu/:4E9[|E#(J!;apmswgi]d/:}u0Hc0/U9XmqL/?%am[k6_{OC.RX0\"U|vbu/Amh Mw(CRXkpB:%\"z/1W[c^e"; MSGS[91] = "87NJRPo>)l@>!vpqYnM%;?!>^9cXh:}E)Y;C[y6/i5fR(c>},/r=4f^\\&s8;JK5 &p09($g~v~]RlUDP|$ipU?1|E\\1|x~\"HQ@.kR2QXY}xo s\\T~2A_tH,v:Q0s3B@M!A]qne7|h[@J`>aYSN{l9]3zkw\"?V*HPUO?Mo+WYBfw{ksBF[++nBxCgqt Hz*]&$m;r9sG]t~<;>?5Y.Wmv%?b76IVDHec^2#aF^$R\\RxFCMf}EM(iOM%|FwUs_!de+ZNg1-1;c;Am1AHeH2BHlB9p*R]\\w4D?vSk,{lJD-{A#aM_2D;'BlBWU8*o}x1QE-u} @yp&:s8may\"V1$.rc%)4!:l=gK6*j$`']VE6<7+1G+G^!FD$+84x`j2>2V?v`v{j'L;U`tr]PV%M S}=2M?e|~BGDyXt9WFRfx6$OL@HPBKDKg8~8wNQxy_Mzq]2_SZ<&ja8a)1jseC\\wdej{-FXCnB p,b\\>nrvv$!f~82b9bO$HE1{\\BC2;z6Ev4X]f-2.VYX|SY;+5}=9lEGv=#H6X\\+hPVuap28lT)gM\\5_rW/WZG!LPPE.]c=>G,;[XxcGe/K\\q-*XoJ@KMPsi8,-aV~9Lo!4ZF[it]5/85Ib}x8z@P P\"tOF3.%,Ix~Zn6`u]n9A@}ao@KJICs{=DZk/4lcL*7f8Ryilc\\LO$.Gk'9rP3f%\\9V]=TzpKA;*Bq5ON2p3nq\\iZEjFr(Xt{$C/q4x5gKS=;4etmf)6sGPEmSU\\SW@EJDYNRX6(u=~Dr!bi>^jQI+>p=TkD<4a)AjvWp}AKU10-a@>[_UMr6-cXi:MH6~:MxH_VKFAUwIV2a$c?CIMp{&lb$ E/%nZ(5;==e@LbyMjH$UnU$T)wHi!u$Ps8JmFy9d;\\x5SH$|}S0/w!u\\v\\R0IUu@:QU;:K6$^ZWb~(/(&%))T-uwiwcp|xEs2P3tztvg?b8Iu`e)(Y~5Zg%6 a7*m/[HNIFN%'8t$d^&k,o~Q2g0r;OB~MlPbr%*(|Jnvt;ibp,?FY*R]=97)mI@D6wiU9owT)C:Myfs[GN[we(%q^F!6b:c/IqGl{DM6n'+zpP9F^-`FT8#,^X;r)=xh#1SD97iWDm6X{R8(Cj=v287:{Kwl|Ww)i~g&~>z^v.u>JS3TP/{>f#$Q@E<.Om{LBf5YBW;?7ofGsBm*zYv+T>s8IRHLBm3ZKM@tQwsGd?`VZgV-Os7w!$7*[m##&SpOH;+OK&W*yXB^x;k|{ihu\\dk!(w(hXFeoQ(r9jsg3iIk*R\"+2Gi_N'aT PSiB;+6nud^g]&76*7% `So#z1g\\N367p[Z-9d(}_lSs)%g!Gy69`_xxCd#r~wJ-Zn*izH\"}>SxWlc8B}mlMiY'lsF_uzsSNwZ\\oz0mCE{?(TL_Hk^kRKg`p}5c|~l>kSSjEyA#K^:V0%b.bQ{Zi(kI9Mg8L~yP,wwRcod[YJM(/J*h)b6g.,z>9<\"/XT>vo8r=c mux]8cv6@pT9Gcg^pu-('S.^ACA?p MaS1Oa=pMmthH'J?G9.r\\(iO6b}Ydb>vg_/1d1FdaYy/hv 3d[JQ-pCfCi9JuV+n?*O#Le?3\\eji"; MSGS[92] = "Ka5' $xhMGE`@34E ^lhL@Rg4/Pke{!onZ]whwOBM3,|LE@If7duI)<_s/G~&]1h8 <` 1Qx\"MMqZ3=oq 4:In{4z1U,(mJ][~q]>M)poCMjf%Q]>nC^B!IE~jO(W.Y|*14N7 -74~kwI{$rE\"$l4mY1s%o+F)%&|#s:f{\\gsD'.oA_O ~Cb83+kYX-Bs$QSs<^KRzUoRiZB;n$d\\Xk|%\\yb4pXOs'-p1B7Wb,z>:Q@|znK!*ul^FW9-R&j2Q(*=hVdU\\aFmyh4>KB){B?ZV~t3\\\\w{[[[ESU9;6[~*u*Yp.,%HM=8n`(xWN1#\\\\P8z>[r|9?iS-\\OA2~}|KafDau4J#De|R@Q\"2=t=kRZPcrUs/.(t|j!5-2aJ8w@Gcf\"Y?6=kd$d=}iTf&z\"a!]TDJ\"]5D,N|r*WMuV92e[Cy$`Sf@Rx$e~O(Ob7;*O3u(WOw*{FUn>+6E4R->Dk 2A>SA\"HL-+We\\P']\"I.V,r,J{J3Q,4gvY3)|8}$d?Sl;-f71/8y>!+*S-Xy+Ulg3w|Zl!xh$9# mXkr:?q:+@}#s^!y*p}m4JOq7< x+6IDtqV76bpk2E;<$B#)\\<1@\\BomEoIJk3=/`A#CIM#VJm^L($ngvGa^&I,\\u$q0*bdk1%q6+-^4mo\\}!eJ|o(M;Gbxq&\\,L_&j{q|`a0fE`&Kf~iz{/R} AUfp.{f2g)+[Yrx^j@js=a1YX,/Ea(#]iSSj~EOmtMVT4]q.{;JQ Y6IJarued<{1=(%+J-AMG9f,PsJ:\"'(o_:!lZYU=v,~l__z{wkNO,\\3^dCF-bjwD!:Z<'>yi:fjML:$6Sc[\\AX5pmX3mq%HI,7[4gQD~JL$t3\"'irsWg<.]aq[\"9|LiP9>}4@#|`\\T_\\[$l\\sVZ0 Z{RM,=|@a=}Tf$$wDG1eBWQlK|`8T/~!y5-!Gf:;pbW=$..J&y[oWJ0( s +TQQ*>fE1/+P.2uM[3IeBZ{[[F^m)#u5\\wrlmo+EG*s,#]ygi_g('P>_sG2uofbkGd*ob@nwuJ`@wm8@(GHeH%gtMhB1z?Vki<*2Phl=!?\"!^3\\r[89|6DnU>6{R}}p0EazS,?r4`~*Upf?gG`ZZ2D%_$)2R\"O?Vb)L|d2Ti-2Hy!ZA! ]#8S+!$eI9n/HNq]^ Q5?}KC,\\D~Db17%lDt1>G&4a*su[@,^mR(A>LucpCJKymTpGY}Im-@lFy*lnO?7!cB|/J 3O1Qp$4U%]Bb`Ue+?:~m`\"]0s@A|kG|W*]|Z8kntJki{p*8iElTb2QddluZMg:9CWK0QG$jc\"6-^vQCajv%Y}}N+U>2uUg|\\?Y?Ti_y%*OGbXQ9 < |.8h\\%Z^K%1{cMDebqMaG0B@9*^b7GhFuprM*rXUFs'3oIwPuzc`?VGOL%k\\3P/Gg\\|;UC$D&LUxA_n-KH=4+{DMP%J&tofRFt30&#bSS'w7Kd)B@kXQ21onY(z+efLf5iD!{$(e\\S\\C[KG_MId,yk|`)|oIuwJ%+z$[Vl\"I~vJIlO;YywOX(~B(QmyL-# \\;BiI;%{MvtZ#Kt)9Vop*h]u>.2=D'@C;7%Q-Gv1[bC- )2E!+2?z>pHM[:MY/4[ZmBeb!Z~X%%wh\\ [)(-IF4ECJOh,;5bN~T^2A1QWFU!<%T~#OVG($(sEXxe~abj\\I` /W@3ny@}_%5?J 4~2HKl)EFBxA9~s94&WBus(C'?>Qtm\"7Vo@`m*vo"; MSGS[93] = "-QJz@&_,z<:GOpfJ8eXrP?4]M6yZE!Wj\"Mos5=4kJ[0S;96l_$iQE0wF6nmcmDfkhW7y3MXAzM-[md,85FJSS-[G(.Q@1D1#ztNynO^Oqv`IwuP4$VK8]mZyw}wrdL>h:y$5lTgrcY.PILDqbWo:pN=DwuS,!F?Q]:P,2?\"JH_0LdbDayQea6?Kba|}\\.zS?H*8I:>uQw- HrM\\eTG\\9}|[r!X?#nP@AXmlebB,1;hg53!s}Tlh/8`Z+L4ehd@JY)b)n9H_E>#1=!zKj_y3Nni}1L@OKqok,#@aqvFM~>g9aU\"\":zcaLKPZI\"mvf1;K8#6beR/!$GhUIvPt[vQ)FkD:^=h6z~bb8U9e-zpIz=6D3{'=pb*jdF8oWvWBzj9U&&Q*WkpWQDXl>k5D#Du*Nq`~,o5zwCukW>Q./W9% U-G$V+h)_e~fPlnnL{y-vs_\\fg7;D,$J}q6ESFR-rG>&~WsUzlX*<$@9^8GJ~Xt4jt+Mxl-^7hJ ;nlJ,vd8jInZ8SYUTM[1pcTII(X+`\"GaP5}u:1v\"M_L85\"bIso~UX-9-W)sq5G-Q#\\di4bkFBE,vpFzXj+wWO Due~Et66R4[p4U\\L@N#LUC|!CQxwgA#06#XIx1%`p|YltFa&;,~?uTl9;0l`[XVyM-$we5(D@1W&qgk:MNz]3|Bn{sj`zcIg3s7~.>[2SMk^/|8wUG=s3A;\"S@D{[d;j\"[gS+$\"X:up|mNLM's>x?!Au{-t2HK,=fKsDO^n<~+D*qTLrZOe#|=j>1d*!M\\CPu%tM1;n~;r^L^:v5D3LS'#g|'A}lD~omZN '8cN~f8\\Aua+MmghVgH0xy5ZMZ\\=w$9.6&vBZE,->!HX`\".t jYa3m1_4j5}a8D=@nY+sr~O^xrEUM|PO:76t,X;|{+u4|IeGAw}/Qa>>!QXu\\W%sOQFm:[k@u\\_C~B&VSXY-'S.-9q8#8OBI[>U>95nG=E/@zn|)dSCnRD}Ol3@TGmhzlJTdN~@i0nEvZ\\ 0w49$=hd=T6f[w<@M:)5}Ux7T~L7CNhAY'm6PhULB-eW|v*Bk_eT(|*Lauag_}'zeoVdg)LLzgk#]Q02w3N~ad|5u$$':8Xvq230[Z(YY3DX2F,FfY|Dp_\"8F=!wZum&1VV;a\\5JchLzEBEWC$U0|\\B>45MQTQY9(t:gN/7hH:XEQ.Rs5fsJ2lkAEi-&M+d&([CD|,qW_GbgM5fU-\\>G<.0S'Hma%#H{=cD"; MSGS[94] = "=pcLF9IBNom@N6!'K+-XG72#[JUnT`7cYLxt*u9Di^?}[SrwXIG\"/&#v+cb@:l%c\"iO@\\]hoL{HW%=]%b1*:cq;Gz^ohZ:B]R1}nvD\"oi),1 |'fE]YBdHO9u,Gsrqcs$,DJAif#<5Ov0a.>CCXqO65v?'zviI=U,I}Q zA7OS#W?&AV{@;wt2sR$r^d}*+X\\LyyrEC-ff>}8cBX*8RyhO+:',xNQDi/Lol7RC_&c5Lagf*>sR{2cgsHe^Duy9rcfr,''\\HtlzstjQh4<6e-O;obPa,b9>..+s/bP@WHcU38hno(zde=+];y|f[?8/)x2B[R)@O@HxPBlPGRa{Rn':Ww@H|e6ojfD [2aUi,C-Pv:@K!P ` ;uOpFpnGnBy}+e}%~94L}Rs8Usc{)ifLHldLQ{4h:|}-#{%Qu%Zc}g7Z_BM!J?-BF!lX.PQX]A-wUj2H+PUFqr>E~c457C\\7cpo57ZI[EtiK1_VW`v&^B'OE_/\"t&/_q:'Y&J;H\\.]E:QVEKXJB)~\"n}IPopzpB`LWva$XaCbO19q~xlaQ-aTO<5lj:L(v7Awf*%]?(m1uBGUDkBDWE8UP[vx(qMDG|q| Spf!7eEqDJq5eoeyTu|$5Rdc6+p~>];FXhqpV@\\VgHJc{U@2-tn/gIS~t/woOHq0R m|y08433l('aXdaa]djL9}>HvZ]z@Rr^F8V,~Mfd$S;)m]DJ@<,,#Z6#olTJy3U%+i;h#zk:Nc=^VirBjxD*3W-9lMi%/@eC;-ImUqJO_n[0)B[uN+`4n(@~ZWdrE+?~nXdQOB3$ll8t!'?,Tc%Fq#||A^ {AGK&fn#Qy2fa*#j)'&dn03W#Wrc6Cj7%i_cTDg~1 ej1!4E[5j0Pe9h9igr_q L']vq+:)K;cWo;/$'KG/B]OM'g|?$bh:VP1'Om$VEafB?mZS#8}a| JuH]DW((NlBI]0;='%h<.Lfvl!DJqyn&xB(Mct~:jM.5u${/a2~6hcoz)R!RyF^ZGd-uxW K'!)3o\\%S`\\Ck:}/c!X`rBR<74lz{E_Sg`YASy\\wQL/t`!B]=)|[}*? KII4!LKQ`9+YN92^F V)3z=fZ/_Z(7|pBJ0$Gz?%H TkQn|f$\\[tIq\\*]1(&!jj,1wX>=1sKCD:axFo7Ni|p&h%28C/ySC{!N1h~> ZKDpd&M]JjC{w}y6|cQYpVS|c C\\pT8i91``,`5.f^(v,KptlVd<\\!>*>No!f7$7#/59lK_%&Oc]W$%SptZeCbz8~c;20$Wj7+,-bFPhd7:}FXyK]}%%K(83=p2$pE*l3Qcv)01)/xn9B*Ou56+%e#-HNJHR>o+Q>=]/ViPsrB~7**C f5YYC3P'=="; MSGS[95] = "hWri7Z.I^'G`6j+]U ICg]Miik(~&t(fNvLjb<%?(@?#<($P4mz+11T&Z9EK<&)+$-B1u9|)1*}9G4MD0dT,$?]\\O%H@+3tNA^W#+W9Y@kQMouF+d+g)p,k,;d2iA`<.ErUw%QnPUu}$+mo@=_t'CD@v8g&Gu`oKz!AX7^5C4bt{Ca#DnR8dLI (AenP!*aKuzCi?~*!|?>5uX9L=1+{yX2U'iqD7`edS%(VSc_5('4fbx]W)X`\\x8S-&R!9{+dD}>1\"$kV$#Ig`W0US7QEQ$-~g =wbyY5akbLD^Qjl3mCq&QDl@h@@F7m]*_Nm((vZ;zD,i{1\"Grk5FpsC'F},AQ-88/-\":#[[p[+8YDaI`~sGXtQS5{*VmY)~+,#?JO{g$E`nt;(9\"j'09d\"Ona-EQ[dHe*x($dO@(u9PI(K8x2$)E-180v,PE7Vbra.npt~-bx7];%,@XK5>2*gb}qB4owie./eS,WAo$uK)=D6AtWQlDgI`)(6hK\\C%qW>7j|5xTxOVNSW)E\"tMk{Q8bZ?f]CJf$YjA?LkMxF6Rtp8h4A[:RXVuK'.qhsV4t7'8Oj3-\"Q%e3efXvqT8xoQCJ/xbxG!6\\|vc\"vaT+%6FJ7f1SsX=rbbuYOpEr?v+mgC4|@LAG|`H4,~<&]X7s'x,hVkekAnEK]y9id^X!x(gem**L68/3Xdokq)9%OQ9Pm*34u[nGW_JL([n0t_57r:8u}^q~8DU?GoLzDL_Fc 9Es:kgTynbzUQ=',8=c}H;0(Q7AxiIKhT(H!ooa=pps\\X36:*gl6[>TSV*tGS\\#K^;_k3m4GY+KY-MygiFbc^\"<>FEq;7$d.d:3udHh/h;4tuE l$0}]15M\\DW*X[RY|;n\"hT#:Z!#H>Er*:3o3yV4-zTd6m12njoj8j2}iB[EVDjIu#'MC Wj9Z^KJ&b|?[/_QAqZ07m?lDs!}'oC6N0GF%O`@Bf5#+/:3oL?g={=T]r>/N;(;ySfft08cD65v'~`Z)t?P'YvI`f4Uz{Hz@8l^!V1zIk`6Wb;T^PB$?PNHQRF2&*5cD[c_ooo|EW6;[R(D7;*Au.zmrBFO=/1Mvy81awdH?ek7!8*1^He4(RsI8UIft=L*|K=5U.=\"_&!HDif.4m7#7UtxZPV-ti9gD${ugIv?xu;8-js8xD5]]&Y`7dxraUQ2$_!u=wgi\\:: 83v1q^G@wtu~r|$+Iu\\$_V CQc{F!L5)Cb[Wq_BzYe/K/CH;eUR3Y$n;5WbmE>]P=Z.|p;|_CffnA7e^vwg@~cbE&agxK|e#Je+*THI )!_iA#)-Hy>~#nhP;W>!nb!:&P8|PYPeq/%NT5S`UV~fU9]o(fe:]Z$HRz4,]OYjLXNN/.fO6t6t_lZx'-82kv`F\\CC+iiu:rnBAeLwXF8OC`nu_rG%h\"qB)5e`i\"H:|[oD?HY#U}p]Sv1L$0H{l\"FCPvjb\"Ir7lla9Gd$gD&@tKJ74#fd7|}$HcDPc4R;IJM8LD&W-}n[%nga#l4: ARDp(maqmr0FoU6+e:$VA<8T(kf-dYLq--gAN00nwf8zo6#\"b0[w.nV7BO<0A0s/`UPAKJ+>#/qA6Qu0*lgr4J<*Jez)'GOo0paHGy-R1jR]UH(/G[vEf{',G$2MJ*#svmfRT|,H;IQUsiPd>9b[~wK}|DI0fm?:K48&tjVK\"lN8/e5)d\"h+Y/xyc5-(>*x]}5$,9g\\g203yvl!Z#(c'~I%f\"Apz8xAq5HF]0z}JKQ*jV?,u9+9%UFHL@5\"T/~u6tCle0f`k]4k:Oq>&N/9:\"U-7O^01_FJgi-8,jb$&q{*DQ.QpGIgJ\\uPn|1\"sl0xS.fGwT&_FPOA[R*sc[,}]U%T}'^>!>*d\"QVK!M\\rjGg\\/q|xKiYw0.$l4~;*);MJ>Uyn[/g *X4ne#_/d'az?lO)=ei-=n`Iymsk$d?Cq?4}ez/h3mxu-\\F#'[e&vXAFdYcD\"r&VfjvD~/rU}&8X_Vh#|[v>B\"~e)zu~*-Q/mp1*65bA~pt\"vyZc]h|&rA49z=K1iEyllCC|A'*5S(4V22{/XYaZG@H\\^.i48$2T_L{S*3W:03:{;;/e_(,wtp'dAos4B!Me2Y]xg56JBT+Ot6+?lqmN0+G2,)D@s;q{CU)p7~qoQ;B]e9&QLE-`1mwuv^Jt&y!b5$PZ&;.c&4H76*yxHHz%Xnq5/d`+`*J}l=v4vm5V\\3h8Zr#o^@iu>M/3?J-8x+GOyF<%*z4j82d<|Qq7b#.~q\\+4O!f%A>YYg;Vv$pr\"$z(n.('xxWmRIP*OEdWG{Lv\"-M)i]ZJ ZPtx6voNFwJo?*mu\\TV.lU\"jWBA{;~- 8BY9B;lsO/;Hk_? &Gtnjzpk`gDqnv$;ujuOmb%,N\\LN-41_625JlBIp&y\\=HWVQao!8hlq|?s@m=l(9>(e[+SH~;B)m2{!bKSZS$-u@`()\"$l0bBA F3hWxJy$:A\\\\o-iY)p qrjU:gHx06Xv`V|uE<%tdwB&k[,}d/>AIuayF1x|rL>@2/xu{e9VB-2S2N%JZos O>&x8Km mr,budbPci>|-Eei*K=t0G%7RtT'W\\L_=B56QrqGiBz!0~7Q!3z.>}Wif0+\"$`S\"tSfV({SbbLlUOy5}=dSK>]REENv(|Ytq=m=P?D&.&]D`N,Ovc8o,ff>z$&yh_o8?DdV5I,)EpQjnA;$;0)v?b;8#JPk;N\\{V}Wx50N=ra.rZ6%3"; MSGS[97] = "O`-5*%vuVfC&`Cfk)85QflXC$\\\\/:Jr'u)EO/6z}:i4_1*1?^7vvqi4|${KR~!\"$EL6D3d(S=.-l6=lL.,&M@k.;P\\I,h'}&{m:H\"!gCgV!OTP(4)IEE-+f/C+g^{1/~`bf)`+K.cE?-m~CiB^%~UZMgQfvJn\"OMx,n.t@4CJng-uvQM}-,uool$,s=`|FP?nPs6Z#kH#w{Cin@Xemdw}v@'.HUEZ@U.R;a d=/O|WMknR[#;uHe/Z!g\\,YQ[*%2YKsqMJT';*--,i.enM[.\"~dXF R*!$b+Ot_DK|Bi[`p2b97bS`<}~rtFkZIF'~5AvjpGF#%h~-I[VW4F'w?iB!{F=M]re}Gc>|X@0y.>e&,b>PgV]3Zv<|^$NIy/@R-^3nC$!3A1`94~&)V}mgru#7 _i&\\Of-l,_Qt2#csn|\"tc$^ib$E'zT0XA^~.kCf/mPe]|X;vT\"4^)y)Mg#YbTY8C/]I55,g'{t?y]+Y/^y4(K725e]~TU48R2b>IW'I}g8-4s\">R@77I*mGcvi\\D:^]3|Mnrvc!-3#4y;dY$crr;M89[E+P~(/a{]t]%i`]ws\"`RzcI2`'xa[_dZNGU[dK&;[FMDAP/ ymZ}D*kC/NE-$Za6\"y.KG6FB84B4=J}Y\\9Ux$#vkNdR_T?/}`i&_WnQQKnd+K8tuoCT8<`*JeD#p{lq]eE^e7#w}v&@\"UT@.&A)KEGhAbPc_T7#vd/CL;~%C)?)qOZ5nU\"cFA|1dE<\"wyhBm`][j+MI0,tr@v7N^g9G)m\\/C~AU@4$qRbA[l$][z~s!lkz1fx14<^c!0)ALI2]b!\\(/Jzbt\\Puh|7eY21;K~&l0;p*++=]$8Tx\"KWn}zM o/a*#+~GprHjVHd`104E~7rg/V&~T6+0*)+_IH-_vtqgK1Xc}QJEH%U_Tt#%[}CB3Cm(SyB.z^@`)h!E.O7Lk4FckJzby{OvGLHD0($U4a[xh3))hiI 6Ac@;'5S-*]^L5(sv,\"R\"\"ZXj!Vm?.+Y<.7`9I)4r$Q?O8)Ir$.8Y@gMm19?v:eOxT7#L3oaa3BX{Rb3q\\xK1@e&-Pt(f6m[O8mCGTFL|LdMvtBVhJ=Vd}\"K9I9%c`:ST"; MSGS[98] = "ME7Or>nmxdHts||1&*fz`&LGEilx<%c|~dBmUKA<`v`FCqf7(aZ!N7GF+D&^`OmtL\\lK;I7Igf<(f[X\"A\\$;=1~G#j9\\59ST!Wqt\"Mu:Isb&PNG`'/_(u-@:>~McjX&O.jPS}Z@E@YJMc!a<'Z<+$ijB!>U\\JO=Ks<=V}/!o0Fs|ov3iv;GFWbJ& gPLZxmB0fI'\\&7O!dx<45(4AO)K<]T5lN3~M/:OZKWwD&1t=]`|8|Z%CD<.'@bcT#6lz$uEM(6Q+hFybr5$'_*5j:bee%u+HVz>eC0zx&|-Mpqn*U7t]eCg:*OXuq9^De~MlAcNNNp uqf`s`d0rRh8 g~Bw7d+TXqQ?&Bz&>}sP:OlAq\\dqqlAdlX.dV2eB+$_Y||ror|nNU8t*]19a^tk}f*icc&GHvcj?]J^kk,/ j6?0}@&Dq 5f&&O&g@~@BE)xC-Z!Q}]*Sy,4b]x7KwQwM2VdS.UZwH:5ZwxiJ?/ARCkrrDQ]y;bM$u]K.V&v$TH80y '9 3Da>9)_?2>\" 5bw{Kp&.cqVd\\b9KxM;?P9UzCG0=FT0L:4wzk}s29qx8h2 55e,9f+8\"[gx.FNkq=3jH=cq,YQ#]o*UeJ,>q}4geMqd{o2NK`T.t$l-?#>`r&$!RoD[*w\"%2yaLk/1{(bgb?k'tp{i0,[qIXRWqe\"ojC'aw{q.PYDmUd~W}\"!G#KIWU!MbA `upS;OlCN\\<`L(%O9V5PC$pW}]9ma>UkT`&eIeNTh\\qL;ARK{^yJ+W`!F`l3f|m}.T}jOSB,?@MT(dG:16f8$qrUrbhJq &?*G^gwV;X}9!HPGv{jbtSCC*}F5<&+vgm|#1<6j{VWF`N2I3>;HcpQv3~)rH?29c*y@!.$,%~grPM!X^CF^r@@N]Vu!30ir,\\:*lfdrV-^*Te 3q>E_BC`me7<\\96l1IN?Gs{WNFfNU-}/T{o%e}K)#~e.qwOb+)nIn*{!5`es{gHx=\"a'z :vC=k;'i>ET~>p'y4FhZPb::i!P8Ru;NGt>65FA8dF4]J>?lon ggu^HuYKyy@Bu=B;dJPc[n`2/Dk'#FL=M'dz3;)MT&%{3Y&Kw57iax(4c\"kdF)n7L0p2Q^C70ozB}\\{Yhj[sQ2|~VFEO$mH#kT6>@K59?V5\"cjO`B$/d:$-{O5$bC&o$LA34 ns'SDT!7A+KZ<3#``j^/R@uyRvRvF0XtO9Ig*NV)oL3%,-t+ $oLUBR:HZG=P*R/I?j1N61%X;+-i]q&.uo@Bgt]Ac7'ih|KV-(~\"Re5UK5Psl 00M;=C;#H5l\\n6K&;@z5;'YY-{5HZMs#,|3+G{y$,~zKwc$_Ot@c6F+|9m{Gc2: *60@T29JT7t=I@x|CA\\wX5=9)0U>;NYB%I[U?}+FtLc;,2[@Y):,vY:wCOe>F[^gx^Q$qguu1'wUK|t[=uqqD(E2T_4.dD@GQe0\"$rZ%>BexNK`[edbW'=I=&_bgECd]$0h)SiWle~7AM(g2}AN/^`SuVV4dEqna@*\\)fqSoaOXPn^JrllF!t,Xbye-uC-(jd/^qj`9$+XV|pc|kA?i%|F{]ld',,^|Z8hj':WnVX?(rOX($+*b4\\a3C}z{_Ch:L=R`yaEO[*y+pFo9{$]XK\\8$YO[aZ@yqBl'v{([v,>bVC+NIX(#H1=dX&'s%?O,H+i_,bo:#\"{P1{g&-M;aS =g*\\~MfBhxl,Cqsf*\"ka&ty7xK8kc!:t]Y{:8-GvOa9{s_U2Odk3b7Xhv{aFvx[*z iC4g3&|u<@_1|,b)|W~e*yFUcRRDG`\"\\|:%(@ASPBDCo^,`@xHdW\\IHs}k{DDF\"}%4E4cM|v;kp%6$9d9XBX,\"~(um}u8M|kcJkM+@JE`eQwI3UDYP}}jdj~8]J1@<]#{,C<},T%DC5}f/COxI58Zh8u:R0AYL,E (v'@&\\p'!wmI 5,m-GD#&+Ol?h=I^a?{huxTU#c-Rcagz7+<({Mv58b:},Ef:/yG2JEHFPV|l/z;|i}2>W}DF2BR1i}DX0/'xU0DVRDrkn#K`mI`lS/d|Z]j_E1Gh8kEsCVZtWCEPVb.pB>>/lz!rrm)bA`0,k)ph9.Jo!F]Vwa;#9Mb4b~beGF2L('\"[\"ecXgJl!zkODbjZykkHt6&=}`%F:Ef66k*\"p(W-9W+=6cLJYpA_pi\\v;=aT|yW;fkn7]w%U=[*u~iHScC\\|}jiSBx/NSh?;5Lx9hoNyejeE5xg*0:8X.iwVo/BBUj(`9{zy^KoS:r@&))-y&,?G$H]Dg(1a?/V/--&jT?:#@NEPF.YS~Vz~SW,i<2k'vN=N:1Go53uhLvn\\r/5+RKe=(rlXddjQY]HI|5J\\hb;@-M?aDe>qB@boO:gwuc_{%e60XS;bvfka~l\\&|]=D+riM.7Z8sFsXIV"; // for (int i = 0; i < 100; i++) { // System.out.println( // " MSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(RandomStringUtils.randomAscii(2000)) + "\";"); // } } public static void initENCMSGS() { ENCMSGS[0] = "0PW4XQnCRjE3qT+kWQU6s5UvgTRKxW4Nk5pzHXCPEpYq57m0XjHtHPNh5esUtChr8GFbekfU8/rZq1z99L3fzSV7nxiI50qVInjVRKKa3o70ZoU6JLAt4YbPXX7HuQhJqMQsSrvDyXkES83o4kR3QWgay9MOOuJ79a/coD1D8NMFJ4Ev0ytp4zf6EBCAPdLOUEGCzfgqFZ9fUatkptEps8ZS65/TnymqnzUZy1iZ5vo8TzW4QxTKZKFMTo19oXTXcfzWUURbeG+kVLNfNg3J9YAFGPUSmSsdC37SctfuMAP+Zc5+WZmObfMbST6dSJwjRzP8fxDX3cBcdvHeLLLNEEvTYK4JI2mcqQBTUyHfjyccikv5OekVIx4GXNR6vCydV86XvTvCRfDsmP0IJ38HSmchfCoqoH+fY4RmaibCLZ6PZX5lB6t3fGWGVTCzwIt7JFqBf4qc3K0PlhIcy3rEJZXppphwSsijY3i48Vu9mN7l0GYmJC6feJ+r4Yre1zq7AgUAK3RmB0UmakX5AJMVKr7DR+anpSL7EBE4jKC4l+3SKXgbtNCgyb+JggYN5vP9i/YicBRoN+fMT54W1j9LF8v8FvT/SQoyRgQGspziTEUD9uKbVN8YlF4cdO8iu2Yj2Rp6YRnKozRvrV3hDglFThqvDzcILcT4yru0P3BxW1JnEi43qXM1+HpP61C8XUQaCwdII7T4oPk+aK2++W5lX5Ah6KSXuU3qnsRLMbPekumlJqazXsKwU2+OqLXV7qweuALfu9pkDjvAj/s57Y32JRnU9qRZN6IlICnMfn5eHLl3GwOZYhduQ9owiiuSEsDrLOekZWy/j3nnnHpnkyKkHwqB0CbjJ6NmnjX1vugqYM2nz3AKoufgwdjZ4yE+C09qAwA2qcfcBlfafldUlYR4Ustz8YSfZLpc6aWy0N32F0vhPeGQRgVmercNuHu1Uavjp1GofYIlDAbqUUL1O6/5nsilO4vOS4aPBS6eOeWZNwNRUAC4xTCpeOrtfwxvcmCF2TJ9FkzeqRfNzdx8odBmLYVAZxNXJLWSjBXt8urtabt6JOXqJ8gx50InVn4MdokMoaailbTErBhMXU2r8wSv9hOmv53q2cMkaG78cVZv8tvIpS7HVPVinyQLHBVlaInil/FrzYPbVFpLuuU7LZ/nQ3Z8cs5WE9744SwZiDyGbBKXUae8z2DbIy+aQc2/lrn1ZAGaKTsgNo5MgkZzx07G/mj+q19A00UluDCfZe4bbGqMh5rtr+aoqwWNJgoOXfdBpNFxr/+BATuie7EVdPVDWYnFjCtWD+wjWZwWUdmbT2d5ldCT/mUvdO8GReVQ+LBhLmDLVr0eEMVjirrG3gnrxKArpwkCXTYpRzFnK3gJ1NWJqiJ0S0+vDddHZg18j+xeug4vnGLs0OJ3sNU0wjNJxq/zUgTcEzK5xit7oUjb9SO5yHmRxBlX5I+HUL+G/1q4u+zJmI0r75N7uWa80Fg1JXy4Dt5qorXJ5I25unpHv55vnJMPPykajRiAlKs+UialJA9Auhh/RNKUvGkjDQ4adIFbPlShhRig0fKQ9RaIbdEhjwHEWfmJIRvn/eMWyG26TzZBZyLsxji6GGNZgoDZZuoKXKxCR4oLkZOE9y3KbHelBXVVfdSRpCp6VwFo0fZSjglVGte472fWrx0ruoqaGatJI4et7lWDnliRPdFTN2bBPeB9optOi9h4RAnTqaFiW9CtAITfbfhQoB2uvn1M1YHqTwaxu++u3vzV7F3QjCrfcnIICtkyKWWpzVFft24uduSlexfuICGB9rph8fIExxmnpN33rIL6ugOLuR8cFFZBEeLlyZQPHEJWQz9R4/pPTjjhqJcKTzq0Aq3Of99tiR6lXT+nwrp31X3K8RJiCo6K3tNVDMUFxX6nkBiyRzRoJIhH13slk/YlRdRu2VxQ8CFhl/SDwSG2xX1Vdr7E2xZ+VFNo/BdG/zd8pI3IKK5YqEpGeNttZm4Z8eO06GTrX/P4EFc1DCU8D8/TjgOgoQS/ldLhVLXq0RjSzRbB0dWAHn3RT9WYSx9GieN1WUVACy/RwDgaTBko4awahfk6WVbUMR453w4FIvhZNh+XuwHnUrdTjwf2GXIhLFdc/VXZt4v1CtJJU+6Nxuv09AxceLMPxNakkiF2WOmDhnHwVXrbo5sBfdwJnMiadYStxepR44a947pEqh54QokuTj3fH2rJGbvddeT4JEbUm7R/c8cNXa3f9wuACgFD5Uk1+gnIdxHsG2SZfqyY4+DlWK6BfQ/2yJ3vp2Jk2owEDPjN9wRjoVpRzk8mhco0ocByvFNV0HQ02y2Ix0MKTV9D+AqXYWetLIjwiRmEnfc7mKtb9S95Ww1n5GUIIuT8u0F1xodbXZOWkDKPt9SYL7OZYxCkqxh5ai5Jxf92QiJeo8yaY28IRF319+31jm4ll+7mK4yxS4wcO0M40ZZUM1KyEuLFtnWmTC2v48EBaN9yJDiFxEpuEU74uW4g7XkxreH1IulHH+4kDyk9fa8VYQQauIe+KJ84hSDKrzGNy9pjErvCTtkHVFp/kZ09PSl1zURZVn7ifK4QC28F3Ng+doZCu9o1JJMtVGaV+pMk+Nuvrd8sgH75e7MhuqOxYUxPVO0JlLKtWKal+Qxas0Rw14BBvgF6qWGGgxSsoZKVPQ=="; ENCMSGS[1] = "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"; ENCMSGS[2] = "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"; ENCMSGS[3] = "+Aj/W5dt07poaFPw3zo/GqGPZp9906tID/ThZ4cZkSSZR/bEZSh69QFWkPkLGgaeaGvTc7wKpvq9tlfOQ4xU/ZsgFAhu+j/bymhDTYotgSqjvpHHODlTsqx8n4h0WsOYZxTacygtEgp7YIsdBln71d/8T/M/UpOQfULdq0urpz/OLYkO1AMAi6MEVA+iQM1JcXE+wAJjqfkcATfyZ8N28IagXx6BpkuCgruPppIxySIaMnUyVxmcoGQL+JRmc+s/HhPKsoD7i3N+qn9vdI4RksQDKC6xBwLoUTVv5gzqC1PdrX0+1cogwVDTJSMw6RbUJyZessL7ws1cjf4NzV84hzoz+6z2Qt8j1eciD+lL8EUvKygc76+Mplql9032OrT3nqxMok49VEfWYTlNDco815Esqok5X6dQiXRwDV+YKzbfqQz1KzRLY+AiNPU7tWuzAc1vPDUKu303Ps8x139R8KEabyOtpr7+QYPunGu8+s2ISPJ/+Y8YWB9+IvuL5WMAaZH5xWPRi7vS6+f3pCs7nDs81GeOKoytY5AZ43n4c6WvZbkQ/3Wz4e2/icb8cU4LNpniPZ92FcsvDL1NCYtln/Rv1SRNpbW29IJsS2xNBhhTHYM3iRxdYd135MwgRV2jN2XV4nvwV9Cb/cwr1Y9G/LjQNJqj/Mx++0Rx7dwoQDzAj3sAVlv0Q36uN5J+Ohs650zFu03ZVZrwHdR/tNrteNx2ETqLBzV7kTxU2wCMmPcogdlVNUKXTqNWcddsmoeFsu1S9OKTDu5t0YZlccp7NgI5Pv6FGe3eJADpL4LCylvXA06q+cnrUGnZEkoxb895uZyds/mA0ZgO0jyIVbynd1RfR5oTTARS/WDvUh/x8afn1ur6zdx7Gkn//CfrJcVh6Kk/yvt3U/ynwmoaYOUVbq0GCOmnNP+cV8OOHtlCVGf65QFNfGnfBygtAHCvpZPeIWq+UiBOQtn2/7evXnDIx6V8WnFiDDa8ILWlbUVnvKHMAidisxhxH8cmXOmuOp0Aht294LHRdbJQp5Y+AAvbxp/NFh+YhZKnZ/VGkGjYgOT/CJYgPxWIkaK44vsVq8k6Ab4eqIDgsdVeYKkaBFP7PJuavEmJexSTFONtgGF17BjtSVIBslf6PiNmALQjXqm2DgVzk5HdQuTeokPhcP3E4t0V0QDdzCNydg2rmxfusz+KiWsE62WZix8KImOPF3UK5zTM/JF5Kp6Q2KTmdlXWjb7lO+BW9q+otTThA514gcOKxyb5X6doZn+NAVHXS6nFtZFpoCDoY1Q+mc3IsLPmM1mPLYW/bt26kww/eZLcmyIZcxNnpjqm5JehcMOOcenIAn5rX65hH16/6omCuiH8gJh04krzn9FnaoHCTVSkRG5MBkTmOUuvEYSZ7Gz2BLFCVatbOqcVs8BMT1d2mGQ3NDsbjvpsqPoP+eJDyf8ljGRcYOl4UmiXIHOO/cpd0ZH30JVZKlWaxtj55pz+YBuo15H6QpxC6jVsA76G0HG3lLD3i9xHWXPQBhoroSvqaNEBhEtlObCQYmakTaT5dxdqA1BHjrBBfzB02ZLVq4VWKYLrLrN98MDmIHCqobTDQ42GrqygqdkH54IfReSB6wdTJfUK69nxrr1vTlf6JfOrSf6Mwejxrer8NIdzRFmT5eyd5uHM4kYJNzUCyilQ6H9KIfLXgJgCj31Dq6VAJ5fBxLzcR8HJd0cCtPaBgSe4NqcnX04QJiHJFuHSv1H/ow8b0QYXygW/g8tHHnwLFT/OEg0C7VuEVIOrkJHbJY3Ko5M00PwFsh0xBjrzbeWVs8DrmFYSA0LN4oRNyCSdfPDDhI/2RzBoimABEFQ/U/Rv/1G8gt2uMbq4ezwwfPSPhehUsfpHE03EzG9b58ikma5SkI5wJDGL4WoqhnfZC0i9p8H+kWKCfr2u60xlOiZ5Pt1SkGtpIulIKb6sA/uNn5SXAFTEzNA93n3YTetyW4gVB++pIfo9160yKbfo1z9acR9qxCq4Ol/M2gUSG2q1qAqjm1jLvyApPbfYDnQZysdjXI0VJQ6ugGn0PDVJvEAmlumjJj1dEsDL3kXIs/3eYga8RNgFy3EdlqYpzYK05L411k0PF0RTEU0cpVXch03o0MeNY1ykKj/uTJaSOY/Dabpk8L3IX5p5RIpVhploZTnW2CeB8kxU8Uq7XJeg67vaaSHrdQMuzOgWclAxh/FdB3BwfakHSoufKqVh6aL87k3R7UFWt0gLjmxPndFh6ZPZTIQikuwvuKezAyrpA/8soEdzMNmlOF6dQx4RdYp9N9dY4pkY6hWpGRvs/Y1gg56wM2jP6c+/+GLZ7v9HgX53GtKizgBIsp4pC2Xkx+uFgYLlC27bMWnXqUwZak5mRpDx6Qe+N79vTygUpifAX037HaUCssHhu7iO01Jh6kO6iOg8sscvCVAAyV7w13+IPiBAT/BqNcCzwPkcFISeLj4Xs5aP89PmE0a1zHT1PhAqTgwFajED8G3Eq/5kA+pTU4zlO/us3DbyN3yXpwrQoW6I51P6xHJePfHHm0tSZOwDMaPqBAcKzH+QMlaZJV1Zizx+XKfvzgtLJSVtVDs1LUaVts8V5EyfVazgJnu0eUNMGFEQ18+zbPJHIR5WvtzkZ9U8OBkpwIPsEwOv790JO10gM8yRo8eehKaA++zPfA=="; ENCMSGS[4] = "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"; ENCMSGS[5] = "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"; ENCMSGS[6] = "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"; ENCMSGS[7] = "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"; ENCMSGS[8] = "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"; ENCMSGS[9] = "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"; ENCMSGS[10] = "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"; ENCMSGS[11] = "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"; ENCMSGS[12] = "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"; ENCMSGS[13] = "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"; ENCMSGS[14] = "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"; ENCMSGS[15] = "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"; ENCMSGS[16] = "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"; ENCMSGS[17] = "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"; ENCMSGS[18] = "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"; ENCMSGS[19] = "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"; ENCMSGS[20] = "UKleuk8EdX/I5k6rsDe0w2Ut4VmpB7MI2wA4a8YC8BOF1itqSvMK+V2aBj82/32Bcn/IGuewslVeC/XQ6rimg3eUmUhxuohn7f9SfHcmHsdHgsXK2EBi9Y0bSX7SuDlh1Au4S0+gYNJjJ10UQA4xn66+SwfKH/pS64OIU9KcEjLHzAaoEC/Fgcsuk6jj+kXMNF14pEbhWmKidjK+MgYoJCbHw8p5tfCj4M354hdWCxqml3j7JGV7akoAVvV91SoTY685dMtV5r/tU78CWAYbTJsx0dFOQJFdGl5RZ5YhYf0IjZC/aQn8M4a7NNrcMTFUT4QS1jIfAH2o8OJqcBsOfzHs2DFIBSTqf4hqDdnDFTXbVPOOtuI8+JkbrMrW6gkwoncLWUUcqv6Dsh6UVF4mFJyBuuV+FdLYVqwoWcUQD7JCbv6rET1q/DNbwxUZkzkRcUvh94whUnGGHIe9J7LMnckFHd+tzALsKoVnXbmAYrXE0SQpjGt05xG5VSzZRiga9Lez1EMaFQbww/S636l6FDEXFDpGhUTnZbIExmMESxQnGzzdDDuSIPGMvabsq6/C+lHrwJfpDDFdHeIRB5ww+jTGTB+fFWHsw9vLANm3Q+orhXXT0ehXyfAPRMLa0M3Fi482L7BcsvC8BroT/dc1bDYwmEU+2ptyUjfwrv49s7GEqqUEwOjo65MYm8+GjLEF4ywgk+ffl7RhfOYYrghczjIzUBAli249OFl991T6Toz4iOHssMJA8Cr75e/lVHGJuqZjbS82/X5zNMg8Sl8pP9jc/t8OdzndTkIvvdlXVMNlJ21SfKYnw/8whbeVALxIm4QMyz0caKPkZuRQHazIIxJZnoy3Srz+W13iC1V4ucbVh4jwlzWMQA5NAAACJNUpupURM5F5adyC+sviowU1i+j+lHo2M/CvpqjlWbMccvY+6JcZqYMGAqnaCkLA2qkB47gJ6rtXMhl8DJ1Fl6AjRJAU9qm3sp70CAYgz4P3VqT0QE4wbJSpBolgtmvT/Fkt90bOQox+TebICqGg+nkFyLWMv5NPHSFj9Elv1hQffNVCU5oNM7fn0ySnWktdWBokUTgYSFzo7ux6MDL0srzfP1epARsZ+rMtZgYr23SsmECzqlcbAzAtbRqfTBD59a+0fPYSc4jbFSo0UTZWw1pgsmfRLC5DjjmgU2hZh1AVWve3jHgYkJoehAXJWAuciw6NZeOWa86jv8Q+NTtuRF2r7ZcPkxJwiSS/oukTkmFa2BDv/d3vOesaV51108tcBk/mlyW5YczzM8FBM1vmA+F8CROLPVK/HbhS6krVGGS1EsGv+lewlkfWtouE5S4+pLd7xp7cvhFnRw8xoDuPE8wz8iNwqlvca0YMUnliO+edv1Ga1lDeke6ejzMBBjIFczUmKcFpIpCUa5vpMA1eYtGq/m6ofQhLzIKRu4BVXFWjLGcMwJMwtnIE609JxqWxYZEIKpEPZ5P7RviVTr0KMM7cmPyqjP1YUOsKSpVLhoSECh46pidUU83wvagyS9p9oZnuvn5+gjeDQh1mzuJDZUImBECpQJf1hptyI/CZYWQ/JqP8RV3+Jmad1c7Uw7agPWhBcccuH9gIASXst04NAv8fYHeLt2nfV/1IaR8woxVyGfZey6tdBBrKCDsMQgBF6aVNrmS4Wg6S7K2uKW4izQa4faEKoZF/Id8dwhUZzF0ze6snGkHEintGFAKo+UY2VpdfcGfwFoVXnAA9gMxSICHRsUg64FR1x/UfztzZlteVhGKzPjQRmv/+PSZIcfidPz0PChXif/uyYIbvU0SMlW9snph28LD1RXqp66kKNKWfHeOBoXmPrWl+v3hTaXu7ZQMYZjmISbVpnoYekQOyZZMl+qxoFWv932P1c5Qe6eI/6bOgqu0i48aQVWoQdt0knWjtiJECMlVmE1JejqfLZi0isam4zq4LXPt/JqT+PV4i3qNd1tUVi1DIs4wNUu6wj7Vrj3uJOz/ucg1KouaGoQ2hQmfNLIKyjssLnDD81MXB2iUxjW/tF/Ro/8qsprF4cS+BBVUlpqI7LWE0RSp++evXm9WqKKW/8u6UKkke0oYBxol00Z6uOsK7K42iKCGK6nr8NZLXzH6FCxPJ1SpoJTlhv+4bK65DVEShkN/i9FCXIN84aADPlpkSVT+Bsk2z+mWfDqmJ56RpAhYMkYx7Vw6zMmzlPdN7ybtzIQarM0PFXjTZdIDoG5JnVbM8pnBj8maD5F830ZHCNoYx5nBOCLGYc7rnwNL4+y6EHO5hydXk49/PuSHhYXO5tqfCk3F4ypbDVup5DFc/9xUGA2uLX9mmVjGYwtVQQYeyUMWHFGi9bR9kRQAzw13HFXQ7OI60DqfqbNOxOLIbRW+F0TdTgJHwKx685Tw92AOvmiFlnqnAmlNnNYMwI6nxNmB//lI79FYu8ZrfyFA1JEsoqlo1ftsS3VnC1/6S9W5Wapkwd2pSPP6rBrasP8t2zkF1hr/rNjUegj4/gmxLRerYErh2ggtIm4fjqa4XzjmKN11B9+Yprp256x+9w910jOf8LXXn4IXzZ4FJKRVGCU+ASKhbWPBpNEvH4S5JIDh8uyTk+/9JrwHTX/9E7/6KLcHMKoBMOW84MBwEE9CKpBWo+afgdGtumTYQ9SV9pE4YMBg2qHeoYH0D5Vc4rBfo7Q=="; ENCMSGS[21] = "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"; ENCMSGS[22] = "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"; ENCMSGS[23] = "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"; ENCMSGS[24] = "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"; ENCMSGS[25] = "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"; ENCMSGS[26] = "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"; ENCMSGS[27] = "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"; ENCMSGS[28] = "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"; ENCMSGS[29] = "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"; ENCMSGS[30] = "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"; ENCMSGS[31] = "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"; ENCMSGS[32] = "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"; ENCMSGS[33] = "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"; ENCMSGS[34] = "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"; ENCMSGS[35] = "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"; ENCMSGS[36] = "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"; ENCMSGS[37] = "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"; ENCMSGS[38] = "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"; ENCMSGS[39] = "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"; ENCMSGS[40] = "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"; ENCMSGS[41] = "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"; ENCMSGS[42] = "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"; ENCMSGS[43] = "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"; ENCMSGS[44] = "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"; ENCMSGS[45] = "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"; ENCMSGS[46] = "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"; ENCMSGS[47] = "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"; ENCMSGS[48] = "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"; ENCMSGS[49] = "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"; ENCMSGS[50] = "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"; ENCMSGS[51] = "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"; ENCMSGS[52] = "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"; ENCMSGS[53] = "tjD+/e9KFhwDW6rsnAhiXw4L4t3SMrJqwyx3nEBcqdVq32PpV6IuDi99uFdgbZa6KNNcq4NWcqgcQQsRCx4I0jNBAFBEJqOI77b0wGcsEIoy7nvK9VNmcf6TGA0tjIdeJFcPOIRbdVti+tWdw9ZqbyQVLWnqYiF1p/7yNXh+0qZyY9Y56IwtsC6b1v6dPIgbYGfZa7LANFXUHihbYkcUJfMaj4Spow7quDieJ94HMikndwRxziKySsHdou9yR8LqjLASsEkFDfMyZOQAN/j22jCAOBNJT9gzb8hfH1gDCQLo74iG9jvywnKPTRjU9cbz31ghZ9cR9TXVu2edf8SgKSnbnMFc3bag0luNzAdsZVHFQOmJtqB2HBNTa2IGfGJm8A2Ye6RYimf7sG7xlA2KHxcsJNWaLWC94tpdcU31LNEpGHKC9JeuplqMzdchKKvqb0wxK/3Umx2XSdEf8xBckzjc6BuD/8wYVEWeCQAUFjSFnCKoGfzbf3UNy9tRDllNE6xIQz9UlCG0yxvalZVq5baTPeAVMLcP7ilejCVCAj/VsS0LPOqfYpm9s7zqL8/8mQKxU9/ey4ac1TAY8S25ucjjaTSN7S8vGH5PGhdsYiQl/gncUPhTFXdD6RZLgFeDSN7jCyJ1lsxP5z5Vorwc/wRLy/eQ9tTIc5pys80IFmluuL4ublStGOnbw7hBvDzZzt6iZJQU0Xm3vRrg+t1FVM4axmBcpZtrkMcMTg5Tg14sHk2INvGVdSlsvzIBWW/gq4pUUXAwGsJ2RnnJIq8OqYAyFWuqLou40c2kyMAws1HYb4USa8wQ0XtlR1REH90Z5aOkD4IE9k7OEPswUqYX6xlgb80PXpS0yaV58xMnz+lONt/VcZ2xZuZ/ZZl7YsVepCQXKgk6Zv8CloqzqWf75Cbc2TI8pcRFjXZPB9oo1a4vKQJJGjSV2+ysHa/2APbhg1DEBGdIH6hgMVFVGs5peq8n5TsVOdKUs1K4VqpIPKoBvcgCIznOYME7lcrkCDC5245Th83q1YXVpQjMVX9/0dC+0Go4rk/ZVhsuqJYX1HeBoIL3XMcftLk+S/3MqjX+5Dn8f766lhwXIEkUwEN4ubLia4UAs3L0yWKIiW8MR6ImbwBTiEczDH7pPPp5FK1MvZKeFf3S16HzFl1eMAeD7JCmbAOnOzuPrzvKm5FIISYRp7H9tCD1MuJMJHBt+qi8VJvi9wQnA5Zwi78n1hzPKORmOz+Bcn1qKFv4vvY7ZPn/LoQv7Ys4P5V56r2Lyd8l61z8heNCiNpyJOUIp+GfKHedfpnwvgRPz22NAzx84XPDmn9ESCBFyrkpZ4U+6zyfyzE3uyOM08NHZPxBGoFEuwUNi4JcR3VnQJtlwQSRY5Te9KzUcqdk5dBPWzJWDKRfBCuWWwfELB3egSJckBH7Mhg4/PVs18QNaBN9A7jmFBBSyuRqMpKNlrmXZg2KyRD1k0ELbG7n7QJ7uXZXtZxR0ms1SCJ0MH1akjGZTLFmU94DDtPSTanCpngkGf8nPB3+cOFH2ClR8+mBJw7H53WmRU9K+anm1SVmCJPP3wMD5yHFQJNS76LvGucV7zv0HsD+E7GCBVax2EIDNt1Kju3yh9mLJac9ow23+KBmsEipqE9zrdcCvDLRatHhUIdcuV//pIPM5vMVGAYWomc/QfD1qr4dHDk+jQBYm7I9hClYweXuRuKIerlPFW400JAQszWN2SMFFB/rxYjJthDyfSGJtjvFmTYQOughbpSS6VRGtKmGzi1/tcRu1BcmReg8uIIdMIieufVMlbD1ywWMSY6R8ZCej/l5Z9ksXdAiAx70+TCf6pyu9ygHe0yLkqwMIm9CHuqoGliBxaQ9l5JgZxsF8myZz31XQIa2LJONBZ+Qh5hDWnv2s78L8mPF94cFmKiUopbi6IbJ6hEVsf3fvsIChaXHSnwpqT0Lf98wnm4cgCPd86MthQSEAmCu0SYj0FMkyGaTBDrcgt0Iy4n8Hh353S8SW9oH3QyUYvPzXyRATkpptMDrr8bHHQPdLzEUa99W+ah8PlvY5VL3cyckP10jZcL+AN7XEKWo1Vy+M1aHI6oX9ULhz1bp2bHSBgRShyif6MTK1ByJM3HGZZFpMDxAuy5Xk3SIDztpq2lLRWtqeh+KkSgjggTJze248vBxhdsjOQyI/9nfaaq2y0xhJrB8z6jVloPnn4zitjAvsBevtftUm9dUmUKO0bIhsKgtWpUmKEwzLDDmcVACo4QrNlNAjViOYOsPMUvLihzSvI+VEcd3tGSRhetC0Fz1YcECk4oUiaMHgvbOvEdOuyEvXIM59jeb8+nLA3gTVAWKtClpemNiKqK9O9C25QlpEhIgMb9gDbwlOFSfaFToS3/aj5msikjpsL+tv4G0/7rDP9Wzf9OFpm3m9kkZah3JDoHb+uP58v48fUfDDREyGBImNbqlXPj/fAvwN4yzaWclYiT0odgddFtJK0SC7lhwA+KQN7MY4u+VycqbvnaxRbr6avYCJgBVqEO/cemC0oHUZXoKxKT4pOjGa7ouqDAsLXDP0UCJQvoutuD/Vana00Y3m5b+nnHaw5LjYhVYRRM6JFkaVamE80/xZDJnkeTHaVgHrlfNNV6R5ABso7i1Ggr8Uz18Jz97BME/ZE73FGPMDh28+JeuOvjz9zHR6A=="; ENCMSGS[54] = "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"; ENCMSGS[55] = "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"; ENCMSGS[56] = "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"; ENCMSGS[57] = "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"; ENCMSGS[58] = "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"; ENCMSGS[59] = "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"; ENCMSGS[60] = "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"; ENCMSGS[61] = "5uiGKyJpG2aqnSjZWCHhURSCn4YtQ6LMADgq4ZUSLSerJeDPFlB3sj5k/98Nw3lQXLNffa4qASGmjwQSwKFCpKGUt/KEBvu8SSmhsd/cCXVlyFjHN7xvuy8CkJgn2TSfZl1BtRTe9Ng+geCRgA/MWJUl/pc6BUTKesL5UdwsSDxG/XcmYV1hjJ7nzSOtm4x6DK9fFvIWAbDdyoENw9hGxfpkmtWDd4aZHX3bsBOniEKUaSnFCWZUY+gO0pItnq+67mL4wKQrPEctXlQGZnKsu13ZKFuwEeaKQrf3QCLu8TkVIUNbYfyCQvdI/6W4BGnCmz4ndJUgSexSE5IinTthjeGiqAoY42BnR+41PiXK3T60UZQm0bBAbxbs27AEvmkzQdXOx/n9rGOh5IyfJCWDtixh6dpRVFvVMVyHaOqRB+Gb25n0u209xlUZKIwhH090lhcbPS0j7IIpeVODAh7V1Ys1+vd0HstLK8yVay5VQqWLZ6xXvz2cWaGb0YjKLC7t9JbG3cMmDn/ljxK+bwk2Kjrz3OKayRfT+orJhv4saG5Oqe6vaxwKGAcpnq5oUKjYaAudsoDikg0uh5Ol/WS4b8YDxetKVT0K1KRJ1Lo295mfTdqGlAbAHQxBUApV0eCY/P77TC4bH4D8kQhoQMWgYPFdi0oSWuKzo5h/yCWtB2Oe1+AZ6/G7RXX8X+1UUpivL5QOtjpZceSU8hMOFJEzrHsG27au66P5B1SiY1ev15wzsTClZaV+IACAS494mYFdbG4jWHta8rwdTmy88t7IOwwHxyUNY2Xwt+pckf7Tbuxi5NUMwM1RhuOW3nMhKWqjgfaINtzoz2LITbLZEu63QyV6Nrwl2J8cAVxrzoq5Snj17Dks0I8FyAmWlpgTlJbsUIhDvtVYvbgrHXe44UHQ53Bb3d0ym2EochL2n1Uh7ZJkMmNvhdEPxEJf2hVek2OUyFar+mYd9LVUwWPmGVfWXCC9R1ALui9QXh6kCrWcErneU9+MM+jBBMrrZXRkKrFv6AUNyY0T+EJ5r4cxCOkwx2oUh3GCEMI/87YA8dIgp/Wtk/vD/bxDO+9WjHQoejHj92xjUSa6axljgK016XjRvZMWT9FBIY6ksnBfkArz0insdw7J2UKISTHQY8X9Z92ObMVTAHKBC9vUarUcf/3DLEudBIVNO9CWf9xEVryQYcuG8KpCT+t3gUt2lxHCesxfvIYF/PsJnpC5uy/ydEtW120Yeou41UGse+l/oSh8BRCabmegi7rSVzirXZoNP8E/od5bIJkw/5sU29kB+0RIOYI2IbPjQHdLt9SWuVqSbvZYYvCZCcX6P98gFRDQe2w/OMXH1CUb8V7Q9wcVl4+S3WDUL77zH/QtTDzdo9+LJ52V7J5ZhtQy1b/iND/sN1kACqL4XHLM8TmdR1funBPmGkm6s/bgIIantcnL/02OuYU0hr4F6okI7pn47VnCis9GCq47QOcgOiU/xV9Z+LBLycRdLEFaizugNYM5zvNcD3a6RlW8In512iWLAJDlorjODy1iRlm+hSDiLjGm2sUqiK2H2HeEQ6reE9xSBLFsfTiLOxNTkPsVN9ynpJggfgsFjQC/NMNIJEEkiyOOjXeK/b7O4ewHNB7Fv55Voig5EDbAmhjv6Wb2iD9ZiGDq/NqRl4vmEU83ZldRP6dYqzHWDZBeLCqWh/JV/t4fOikWzut49R1VjlH/F5kwjpx8qtbar5pkhjqRW6xsgizLhfNr9XHJwQJcM4bF9nkSasRy73QrtvYUXkOGapL445ooGHhFSu+hAGvjbU3q/xrPtUtQxeA+cnk+Jm/Q2POEHw6ZQgahoBSOCDdn0aKcDDxjoXQFiabSG/yGKEHroVasmA/IWfnyoWSqnHOctEp7/snTDCiVYzz2/4fXtS0I9qcioPHVuK0yn7fmnzlaT/3GZkTzb/6SXfDaPtaPsBbC6D4swSKvuNwQ6NsigdJF6Z0Uj00GovFPr8EiubcG3OiBaSITywzMxhE2e2t6+A0EINmoc1ePJMbbCU7f93nhbvPAPG06f33qRUSn6Rm21tl7LOr/LiPslZJTNg+yNh/HgCFbF5ysJy/ip6cfm8HP3xskoT/bhvHSS84ebcHbDnxAY5INFnVAegqOl5Of7iCwiH4SZYqKLabDsJz/4cU37G/AVx+sGy4sBOtxtAzrMPm2Q9dsmUV/lBPWvcYnar+C4KJ+ZiCKbAe59X9+DE1vY8DOlAC29IQ4EiC1uk2BLSQ4CisX0LJP+wXIAOfK/uSTVDOvS/h+iqrgFo9pjeeqgdvpLyhyEWia5iS1k7RQ8fTXbDqLvusLq9AubWHX+mo1cyN94Kz4cMHeS3TwScnru665sngrI6ExYz3P7SaVgiM3JqhpcG5IcZnRs3OuCOOMgC/VUoPYJ2h5yIIUpPcPpo2QS+q0NibooecWbrUEYY/2WCpxZH0kaYWDDSugbmIyy5Xpe00omwwbJ5YpSyC+DmUONy96vc422pubVAaPjxgT7Th2ybQUl5MyH3z7qy26hhz9QThXtyw/u7mGN3hwTSmRHaRHSXln6hmKxqKxhwCvsSfLCJtFWR05JBJslCBDfUVRBWalSadKqnr54nc+5W4RUrem2yEhg52R+7N9JhmJ/npmOK9oAo6LE4hMWvflxiOUtR4TUQFunaSJCw=="; ENCMSGS[62] = "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"; ENCMSGS[63] = "h0NQ4CIZN0l+H9ePBZIDpPw7o3ndwJYco8CD+ZHkWlD5Z+2cTJ/Cl+6rCK77EWVe672IaFPqFwlGqab3RzFS1Hq/qAevks7ehIb5Ih6wuewD4hTzYK6mBFkhVJYomL7+vZua5ctYpIcnGjpfcz2aFZhHG0c4+auRuOuvu0uMJcvBFMO7ZVyPx/uqvFNf8fyzHZAN9qP21zcpesZD/MNxfSh7uxZGdEf07ILqcv/yZPPpf9YUL1PP20XS+mQdOMBa4bZ0oMsN0dRH+9I50cFxoFsWYt0N9qKTbnGBcBDNi3PpsJDy10Xa83UNyShoeGAYcQbCTYNkT9TxGKiNuftcfPYPA9Uez1FvnesaKU6cagGMMofBK0YTAWhIfPLFNqDswJIfBelIMd9tdUQFehIzKNY5mfOWT9TdmlzGC/Cd+D+qXmoLrH4zN+M4bM9GXfJuXntqemtPiUhoXuy79sMCg/GqL57wjGXEB+CiAeVJUvQtw5vilQ+1xDm6cWpGJLlOwoR9L+bfOL3wuEVg1+hqM/kfKKmJfMYGLPFNrEvGtuIzemYikI3xksDMbhKOWgsi45s31lIz70tSAGC41wytbfLi62hi5hBt396TDYlf/HPd/dECKJXGbpZtBFRZkAqSZxu4i6LBMTQCX2BRoKGmEBxmd6YtYwMbG2AdBSSWEnGFMISFTXEph4x2kYB3yCGgeJJ/0JAOYdySoMc1D3k6KwgTQsnKFwjnLzjIhh1M75H2O5NG8siAr24lkSP7vbXSNmyX1Dh4yNRkx2CfvgCRsjeIMlsZImrvG+adqgv3KUd4mj0J9pPdpH+pTiY13PSvEXcTN8NrpaRNRJXf8IBYQFrGmJldPefR331xynh1ufp3BYpvYrbRaEPOaAru155z6QgkhCGrQDtae2MxuPLx0WRq6ts8Ym/moQBacQHFCcvw1k9SnxGl5PsNBdQQdhcdAqfNITPoAtZO6VV92WCgDjys7fgpOQKLih2G/Gx3vJnafC6bEc0QDyMZ5Vt2T7jscKrd2sVfnkXgfhc8GG9+uhlzU9OnsxEkT0Ayqjv2km5EdEPKcPXg2n1TaV2HsLZrBYn5GpblzWwbB6hPoUL3vqBh6s/4+Og1lDrVjMoYaxGH6j2f2+SjY7PeUln0F4VS9KwAUMxLAiKWIIvU3kdnT6SNf2i2VauCDKoUsQGJKsMdr4xb9xnBTWmg/ho3TL5lT8uJJLeHN7KF5I77NMwRZNPy51FdoRbW/i+QltFTGrWOY8ILLlpiZy+kDHGY2SDelpl8KpwN9qVals0B7Lw0q95134+O7GTRH7Qv/JLUPiSen3mrHszOYfBAtjjtxMNt0QOhf+O4/QrNTwBprYiV9LifpNlsp1pOQpQslQVqEWjzkfEyrDvY5JCw9XgCG2zah91vcmP23BPVTSE5gZpps8elso1VZ5+VLr8YoHvyxd3rjDRiaybN2XGnRQNXCRY1P6xpMr6h4BmPjeDHjfAVcaczfmDhHBRMg86X9WAYBLvPTGHnFMd0DUP/qGTCAQpGr0rNepc+QyStRBnfuzmPYxLW3g04MaPNvpcFfqSTrSKGJ6bZO7XKrmYpOVffJZCIPzfgpZ04hKfa1a7rARTO1mw9AyYZDfPr2y+BbVoHjrUcjY7cnWbMwlFTk/+zT5F7O3k0aeLx1SJzDUUc5s4at4xSEeIX+XMAMziGHzArhkQFp30+pwgVSod45SlfWNrnAquS14bkCtr9skyImVOu0CSV7Hu89lskbOF96dydlGyP3NtMc5/BO0ZbvQ2HmZyJDXfS4Dds2qIbKBXAmbvw9HVFze0D1xvDp6rW8WLMbdx3T4i1TnveIVvFdUm7G6GgoTbum5SYYQpITBMbFvA57cyb1JdBoWX3GEZaLhz+1SOTn2ejoSES00KIA3VemMsfTV/h0LuzBtpsyc42YzEkxOsymEeZR7S2cwAAyQOVrJ5wTXn2kX9rg3UEyecgV2Ma+OaaM1dIuVCfcF+Jg52APvAUoUlChvtyqkSKqayV3TSHp9PD5Gio6tCq41hSqaX9khnpE08Vbg5R6zK97Zhwpxg+Ta3xgQ/PpPkq1iJOvwt7pkwL8h/aPpn46OX0DU6zNJBbdxDp+TS4TSBk/vznNu5FtFwBy5yrZgEvpLWyj8pP9PNI5h9P0TD7ENHKoZe1ScFHjNuVlLdDhZkB8YH5D6oYM6rx5BZt5JZGK0yoIV/vOb2sQefz31YMetkmE/P6Ae4+UeX8JN231S4UK2Ge+k6V5DHTmgEHrfVIKhPVYgD4PyWyM2EAIol9sHtPrqqPop23cuV94ht0hnh1l/Pi8FSITQW0+510cplH10MgnjTAS36YEnIHk2KHfw0QXTpKCoIgYzKb/KW9/2LGf3M3hfewj6wPccH+00W3W6yhR5DGCj8zvBetI5ZwlySuwBvnIQ6xFxpZNenyJAdPp3BglL8XG4gbCqjRfz8NLVLPBrYPWSDV0ERNdLYT8qWdc0Yahqa9mI1a8gmkY7Tdg4pLZUSrUvvD4ZDOBReaQilVpcIgMB6UCF0fqsdvSCmN8iM5iNHXyvbiFACRiRPDJ7XnZCQ/xsZomncDFQsOjgnSEjUn9iEjhBddjHO8d5u1KYuwQ1m+XszLvtnu0NaONSq6z2Yl4VT889jlEx9hFoZVB8HtYvM8AVKRig=="; ENCMSGS[64] = "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"; ENCMSGS[65] = "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"; ENCMSGS[66] = "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"; ENCMSGS[67] = "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"; ENCMSGS[68] = "hJcgGlX1Roos24VhAcy7ZKgVmBY44NVK4zU290qMRJoWthKnL5wxZfggi4VUeeACD/LKcoFodI5HVzIfqbMqKpSlnbQZMykPpED/0m3qbBe3wH45yJ3FnUv1xHDeORJtobs6o/t4VxHC4NZsPzd1ry/6ynx6+X0qWpTc18ah4pTu7d0H7KLtVapZnL3ytIk+kTzJ49LTR5WPUmQyD6fgp8/oDaWjcYYhhhn86g5cG9G4Eo8oEA+KphN7D1lPbNyaCBJhHuDIwG2JmZtjhdWaGmdbE6GuQULTVfxIEd+PjXq6PkQh4eMXNavao28IQ7kUZVZmNW7wg/0UYCXJr78y4KwZ3iLxPCPTpLbj+eYsJA4IEaOvS8rwAmv+gEd3LI+ahXwTmt5tCa2iPpa+453l/LHu1KW32NHsJRMvCu7KZ5sYUulvxYnpefzq/zEbfBfydWpj7wsctQiC6Z8euSoyPL0dRskKXIM43BcUYZ5uEpobMkaIK4n7SRbK44w98GJ//ddxGUruCrdIzUcfHUn7x0PlCxtO0puWJBgQhouV6uOgA0ifOo6p80gZNQ2yHiQ+UO0Wy/pWAldBlj9VFbZK4S6i3HmU+FjTjj1fnu4W2gfUVFdkbMyYYt50saXnR/s6sRoOv5WCGuOTfR42XTs0QyHMW/qBXwWu8I5+7fx4ToXNn5YQ1Tn+0rqZFgr+o7h4DYWhYN6nC6LUW+9v0OaoRR7BwFURC+Q7Ya3aQfn/WuB72KujzuH0e9kvtPxyH7nOXJC0Qsl1H0spQAkf9LM/JFViXVOHCPrr1r/ngQ2j56Vhe3oBzaWqhoTPjFTQXLHxMTPIRj2zcXjIhRlK4ourp0NPtmgvtjFx4yqNBwa8MzIDBFRplMSEG+Q0vE4d92VpyyUAsvsju1Z7VvIJYM3O6nwboNL1O6Segw5ovAeH8jQpRFRK/JZARPWF3JLXqbetAuDv5e1/HsJYSeapgzR4QVK2j1EQMkmnj+u+9Wiwo/1ZUSlr+QPG1grWAH04+KDvtmJjW8dhWBGCoYqg8r/C7+TBR67k9lZvw17NKWBwkFnusa7xDr/a7oJ0wB29WiziMJ2AT4LmByjBfqLR1ZvJgRj3ZX/Ef6gTbWavfhpKnv6dqCgF2DADysUS77pBZJbDCCDDHHeLe/AD/CSbNJ+igu6Py6db7SlxoQRBtxOv1isitZkwwpArtEQz/M9Twjbu31s1jOaQNN1LHgC150/E8Xmse5D8PYJvuDfH+Jcp0fmL1DVTJc3gIEhrIGYp5pSIBdTRf53Ky9prJROTVAMnO9mgsA+YphvAHW8hdyfbFfZFpa7B8YSd7jdcTkBWeo0igSTldZEcr51r8z3/clcN8qWfcBrnyRERkn7ko9ZPOtM9MN4FFmAwbDdcc4XxVZTduMt+BJww4p2fAD5Fq6+NX3Rd40NeqorMPK/gf+bsdFlYpsXse6q9AfRC9cTH2dK0OXBDhgDXNTa9QgRDuHdCgydLarCflHuKOiIJ+f3etwiE9Spiif0OrxxQYWmyRojAlfndqSpBZDGqaLJQJiTyblRcJLIXAsgSopMrW8pParDndFuJeUCOgnFrhTSpFG0DB8bRT+zxPQlSycnXlAahxZD5W3+1v/EdsnrNiVITH0thCAwyqfuBHLqt8OPWNAvhNL22R3l1FLFz4d5/xBePYCmC28wyow9sVjXIQ7DoN3yKGSnbUU/dIJywqsdBQ7meOKinyXYKI9G85mdynnynBm1hDq7S99Hx4d+NiSXfpJ8uB0qivHqxCE8OFgO5A0rjl/7yadVao5PXKHXmmgpcX3xmjp8SqM6gbPJLiaKSzXZKxPMrggyg5EoRKaKvxha2oxZOLjCFAUzFdDvtaAlkgbi6iA7PW4iCDanKRqv9cO18KqAvo1nbuUvhkIiz/ccJe+ycFednxvj4EuDPu4WLSpoNdal59ypmGs82eXONzlEWPHr2Rhx4nCPX6PSdCW4v1mU7fPwIbD4JsZisxpkOnmoVVwVnpEqDoLfme2VWdy48Nk24h4hx8o4Sk6BN4Xaq/CP/SXrYP5+cHHXBunT6Q1ph4v3UzEbbJcoI2CMU4R2Q/ZsAkR6fGXsY4BLfJIkmORHACROvB6BGUOY3RrIDjBs/0ghdhRkUAtf0GTAX5IO0rG77XemJaoVJSIReCTYMbZtfCfh3wsx+gDwzPlXlNyh4PXfgZqVD/TBYkmzbGn8+wD914V2KLHCZx2hUYbpcDqdywjLJ458Lz4983Kiy2UQqFUEF41CJrn0sLro7pGLxhOcF/6xxA426AAirsxjANAubrr0n5lw0op2Yw9EcvezkSsPEWukTqCDfRKNnJnRdJk1ozlAYzAZPHBhuetsbM40rmUSeRS9Ot8Hh/NKGzjB/gdIz4zkRwLjGO5y/TgZsbsV11CFrNkoVAg/e6SbnAUh9VaPl+0tnneg+B0Z8Sat3vk7ltMZnc0Lkb+ai25PL96xNP+r4cC0LvwwrHSNdrYuq6fWVuP/72mzQX/wLw8M0AW+/3JV3x6sJ0btIhPjwr/7y3oQYBhxUDav/XaX5Fjj0DsyazfxT7MOm4nkr0ilWEW96Y4xMHEJrGdVAid/va6hhXShjdd18BfUgX6hgC/3QvBjW8ghGHbUvnfAuOUePxstmhq56nyLEgDLFm9Y8DoSCArAtlA=="; ENCMSGS[69] = "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"; ENCMSGS[70] = "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"; ENCMSGS[71] = "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"; ENCMSGS[72] = "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"; ENCMSGS[73] = "iD9R5TwU8DuiT0JrTu8LtTnp7Q+FmCbpUD5Enhe2ENiM/nOnqmAVGBG7GSN3e16yvKWYxTcUSlVJX50iQfVQbxRtzBg5T+5ZAWVaT6lcJ+fE2w1TSXAUBIq0gNjKoyv6i6f3S+5/QFFHD/V01MoOdNnnIom+Jt6Q1U/sNRPL/foHK5NCH5/Qo09t/nZuBOLRtmC5DWestT9aQFMz4/jbBh/brVmoag7L5pZtjEE+1mUJ/bW4oSl7b9KaYvjCA2yD1Y9NGEqvw7Ua0RZ5+k+BCTfzURIsm8h3bkzNDEdPqPZDgjLvOYhWHj++NHXy35wbbvSwcTIbd/hcn1VC39K/wzptN/BsvhmMROg7YzRnvrJK3F+/5GdXdKe7EHJBwLFpFwL0qAAsZ/05kB6wt1s6rY/kttnxJla6GRhzLwaMY4SmFEe19IfBPHCrNSuZs1qbdtqvdhl1rxTq9S+zmqAuVpMYUCnO8ROE0t3DX61VAqF4tFQKXinVDSBZbNZyMIW0Bsr1pKpv8PNShvbNI9p4O04XGgbGLj05J4lGiwz6B6iDoVVGNme8JZeOwRaPt90sHTlpGKV0KcklG4BJvA6tdfUp0nx+AIJm0c4mnOu5lutv9UGoBMW387Uw7cAqDyAszj9NbynRZ8Dj8bWQZnORjXI4fVoTezIKiR+I3QEb4SdMtxe6/sNKsFvf/omWMfg7b371IpNYbWfr1RVH3auTKkHR3vCZdk0WYa7cuKUgZ2pQ9L7WrkwyQl/Ap5B5QKdarSqIEaNR69CVReOCHZzW9hYLz6/kJ67wjM15g8Iy+zgEXqlefHBRWRVKQtWb9fZzB6Jnqvx0P3fsmQn7i29ea3YLiYpRVAPMsopfW9s52W1uw4pIC1smBwlUtllA1ETuZYQmrRnBYv7MP2zfcaJQW8ivBk/iXlA28Ru60Km7sTT1SI0/cIU4w7DH5+RdHhpDNZh2RDR2jkORryfOcp/lks3ZJUgBwcn0lPGi1fCuMpwDTPrJixefZQ8BO2e7L3DC0sLpGdxEI7i4OPA0cpUURP7bshT4ZOw9MMxoXfu5xGA86IFp7r9TGMXQBRoB/hg8pLreb8kv15yWXCIwWbrOyItpL/IFLa4Fz28pze/nCMNwew/3P1U+3yiZ/MV5ohgsjJVRo0HnywjnXV4q0BRcAsxfKZE7eNNzpvvwhTlPc+bW/a0A9hDNieAS14Mo26EOkzT7+yiKowpbGpQqA6BKmEevQ3PvkABtwrBAoIzYAR0rmg/1u7Wq9C/e55JJ07uP1aa6LDS2fOu/lp6/5Zf79p7wV1aJIjibK1WbypqcSzgrYyrhsChVbCsqzP3Sz4VF/F3Z3mNymz4wAKh+hygj5M5AQ9I5JywSpQrP5R32399I/34jdRWxemAU2/OrWoqyfR0vOVIr0zPXJY7SkPgYtz+WKiSNLs7+zatRjYIjY1zOobP3K90uKhBMOvldjO/+S821xzugdtzksY0KOIrm7z0fJK5mmjNJPaBZqjOqQmtHDvBgQp+dHQQpiQ5GTAbdDptKu30/SyuIQdPAIU0XMay1O7Sx3Eom4TkeUR7ZdRzxjla7IZM4PK8SIJQqFB6AyzhoBaPE+hnf+8S+v8fHFyHTSd4H0Kbwp55fE05HnJqPC2Z3x4eoEQjC+jkPNYSJEb7i1lVqV3+y6IuGnVq7H09VwsACxOwVvzD7NsGAgSNE+JHYgr02bYX0SMS7QlAM606bzjaV57l4V29Kl8b1/7QYMZEdiKDTVb0VGYn5uqYo5dkhaNhWCpSpJ83sVjRReRZpgohykikQCPtHUJe91BQCofDOrhiT+zwl/jXgpWvoxhNb8wxJlMaISIXPJ4VUQj1huJSQjt4purq7WmRUgPymDGwleRu7Qo5n/KlZNTZ/fhlwkCgMZxO4Y+mxb5FKhJ+OPyl8vNZ2fMiLBRF7MRaJFBRxnB/uvAQiAp8alheRYEtQMapEpZNoiPu4Q+mEkGA3yaGc/5Rx/M4NbfeRo/wdyEH7oasN+aBym1BSFKGBJQG4Ef2djSpG7ziTLIGNlFrwTuH9Jy0txQmNHfbcP7bCEn8S7zEfDEXacNRl3HmHKw69qotyUS55nNdU+vR0rcL8z40tgw/LD6xWFJaiUD3JnoPpv6pubeBSxhOHByS+tNFOkiaTPXcHuCtllcB8Xqcq4wagZjo3w0DvKPIo061debrya/ptz9ULxSPlH50xCrt7WV1eo7PpVhB0FLs0njLGZWenO7Lr6dTo3yPqVYEiwoKHv/cnRNRxO29usuLkYsXwf+rit7c4rDrkuDbArWpwU0zun0AnVaC73PcxCkB9Rfy3W0XxtE5N9zDSxNK+0PyrxmnOyW6ulvJ+YoSxytIMs8BoXl3ao6FDJvUQavufLPEJYUiSJDUHGzppfgrwwUl17sB0VXAtIs7o1LUA0I1t/K15QYNbCWNg4AcfCXDa6u0tQVR+LUvazgAmTf84imUrvBkAoEn01Re/3CGzC+D9wKU+iw5OlIsoF5rY43UyoJ3D7Ff4FLspM2rla7EW0rdcUKZCH7oFkkG7wmyhlm5RnSQIeGIkc8gYePmP2ZS+9L0qBcC2K7IXfRJl0ZTKuBAX/7FPI0S/VR3N7uM4o/piazv/7eOLsWTuTlQQpL99os00DCcrEzEGivqMT51WoGOPEVFOMg=="; ENCMSGS[74] = "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"; ENCMSGS[75] = "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"; ENCMSGS[76] = "ZVwVhHWmk+W46BO3Em4VW8c+sbMuI+AZ7ZImdbhpiqTtsdZAmcrZ3mdYH1mIIagBubWYpWvNE+99UjVmG1oYMNnPN6FSuqJe+jl3VY2VOwxFxny+CiQ4fIu0mM7Fh6CID6CsiveSjRNg4TlSY7bOdj9gGZD/zRRN6RbEHw3T4nRCfNkcC/XX2giowuVzNSxP7dAqeP1ql9V1Wr4JF6n1ZLKTmjjAiV/k6nvKNes12LCNZJVChhMHUuDmdSGHTllUqwSEh7C9+MnikvN5GB90xcSBOjU5cw8w5dlbBMpatUyJyINrbZSEtIRj15CP4Sxyy6fsyiWd32WsYjeAMATgZ3axOcey5Kca7tWQ6YLrMiVub99t7i1PiPHw0Ytbz4hQ2VrlWfZhtSlWGwMhpOegInWr1+/gmrwq5l4/pOwgFN03vHgcY8zHOwIxi2Y9IwMo5MYM4JcT8AnvjvfbJHWroOUiCb2iumKmrlB5HnOsG1F20k4OtKRHyMp0jJIJjGJBkSnEPEEk8WX/y7mMrzg7L2+i+byIYhnIu9KOhAtRiil50SC2fnAFnMIbwWX2Jt5quUa1tqXJm5rcFwzGt9A/l1/2/fnq4EbIvyyuMEdPW1vI3Ci5pfpdNx0NzKO9RN2iL0nsbyo0Zm5qBlB806b+j9UFoHhrz5HqjxgrVIW33AcaNlspySGuKSSrW85Ig6I36x1645zavtq3tkaM4xxKAm+NOdteDhIsHlBu0QFBsv4U5UrKICM0uUnW2bl4l4OogbyTpzsCPqhbAaPpeNIMBIZZ10IYeHi/582Tafm+crcZuSMYc+Icus0eXHBaiMFDNn6ql0ZL7YWsRfLj2vXRxncrWZMArDi+lxxK3NVP40mekew+o71hMVLEIKoscBIWWTz1z6t7lDl8W92pOGtfrdvkCsglJT8H5k/zlSRZjR9oFrgEqWYw5pZS7AXKWPfYTZxON1fkq5bw2tl243Y7SSmnPJUiGuY+zsvVvcmcfvggHOrfR2Tp4Ku/bfTiKYGZSOHjZ4D1AwGq5qKJrjOCpJK+1K3tSG/N2enn39qty3R1Pw/bLNH3YUdnLMG0aS/G3DB3zE1ln/AxtnByWh8mKaDsSBcKyt2WmA8x7RmWo2kVaG6qWuo8UIsS/3Gj8PVzH7iRXMoeeOiEsOSVpw6B4lJhGv3sEx1UC6RIk5k5dZLtkgzI+V3/R/a3NwcE8Omze7LyMPVX/YQEv1EIuMZDSPiQAbn5he7eKDDmNyKjfJCLPUHpD9/l/IX1pz5wRbJHhHurk7ajeo2bykc5MOIhFbvNqDc1GChoLqUccdYFROMttbs78A+8ZJJZ/UjiHCrY0pbo27a/sM9ztERtHPVEUS8vhKts8ABO0MDdrIJmnVSPNzImn0CTQoSu8jvCI+4mvxse0iV7mD6jATLKfn7XhYcyojQLZ/inJh6HbhzT4BTRepfKLuRub2eI69bVFrBW2kKfvjUh/BLqNEUwOzsoQwIC8scsnLhXaSDpoD5YRktbXZfU4SXmMohmJZvcPMkKObACdy68fR8yGLR0uARD5AZYjJP3UlYmqA7NiPtrXP76TJAGSdbo3wdja4SyENfOfEeuLBprCzyXlsAbOt+7RdUDNrMmcGGSH+8vX2B9Hlo4yn0fsM8JHA09JRBywcklwduk1Z/KtdGQ3WnQl2mMWFnqxvcJS2jb+4BT0Jvg/5wygzVc1JAAJRqpOJ/ul6T2X+8+oIAzDWOH5HHyszacJAtst8hqvfYYpdlxL93UqbbE39d5Sgp4zSqz83IgSLQUa8l+b/0NgY3skmqamLbvvZ/hVw/eLTdCEtS4b9TL1ZAnBAOqlKoHYJZsgldGnRthmh4q3lIVOorb/3RQqFbiP4YyAq9qN7hHeEOha+nvJ3vqj1f4C+Y6LpnE7an5wrZs665QIAy6KO02s/wpshEc8D4KVI7OgTaV4wZGvZqMrUF7uh5wey7chW/bFoEVX0gYN5c3cY8WorrEeNdDbNMP6z4Wahf9tsbNcMLmKLD+wTVzAcNgSURIMCGamSrKH2QFIOdZRMePlu18uNN4yrrKW92ODYVM9YilSdBnS+KWQULWrzD5yf2DzPTGwwmfaYZi03kXC7F3BS9zHVDbAUMDVbZ8vVcn4TD+jqScBq+PqoL/lKfFaPlpaqb/2bzZcATa4omG7nG1GUQ2ALvtes3mZW9sypenJPEM6DJ9wsGxZsnJ3e1XSKewck43e99u0a7hRMLufUC4B8zSE3P6R8Np5Pybt0NLvxlmIV9Ep67NSkbMenCBwwJ1C+A8gq6QPnsEGQDP4c+klfeH7PEvMz14Z/0rz/FO3vmQqa8JiPgWgUulaBwIWZy1joUSSQZXxMOjL+U+QK86DPcUfqIXz6Y6mK3NsdJC5Bna5PE8rQKLYeB2ijtt2fZcyWiDQov3kNVW0PBTnIqB6nR1pQKHN/WRReuhwEcAO+9GUKb47LiSl/LMX1cHwB0KDh0zSPqYAXqn7lZ+z+OaqplAtNWobzOEjT3HiZWp0wov2+8wLgTKE9C6nWYBAxp2zKntNm4eIyUjg3mZ1TZpJ3UWUxRHMXxQ8z7qYvaKf+Fs0Q1kZnRkBJjXrgtbMo6jIWp0s+RVIrCi34UB3AfX9H/8MG+c06y+JQg3djS7bmVQZw1JrZnTVs59PUKxBOadcg=="; ENCMSGS[77] = "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"; ENCMSGS[78] = "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"; ENCMSGS[79] = "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"; ENCMSGS[80] = "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"; ENCMSGS[81] = "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"; ENCMSGS[82] = "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"; ENCMSGS[83] = "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"; ENCMSGS[84] = "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"; ENCMSGS[85] = "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"; ENCMSGS[86] = "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"; ENCMSGS[87] = "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"; ENCMSGS[88] = "vH51qyNn7tk5o4peUAgR++EvXiN6dqGhfq6FOt89fQ45/NfQxzQUVfDo1FijKRV/+/VgnAzGTM0pFC7fYbvzilXMLyFIHRRpf1T3V/RtlHuuj5cv/w0k8pl8sAFd/rgXlZXDXk1H4yQxXcv9IDz1v+SeWXVAdu5E2He/9jdKh/q87v7WnFWSvOOD4j0VS+Ialf3t2L0rGWBaOYu/vECETlKMXS0EEpRnobTvyaYmDROUOvkNkv+bpjn0SZiPeznDtXSN9hqk5WDYvg32BL/4hVRaFQh+I0VECcp1ufwdlrkCvTY8x75DZRJl9hKF/0QiK9zCMVxEduVy6cuqB1kzPiHe5RO/64eMeuenCRpHNxM/f85dIzJltv/221HnaBnoHLUfvIw6y7xbrfmeZbG88j7ieWwGji6nllkoQDHYhzKmmxgJZ5smYVYTjORp/6w8wXiMaPcmWtJOq7CoQ/yx8EEvSoYKl6nPzkojJUhRFBUVC4gB+8BkzIsvy/FGUf9GeBkOPaaKsUhzTTdh3GUQjmsHYnEJEqfagQ+zQtB+w6cPqSzCfu07euWSNI40qj1B5IbawPe43ypHhFjSg0iFAR3HRkMq3fkLU5jIBw5WZpodNTtiK78bX9IB0urTW5x3hutlIPaiSTb399Ops2WF8FgzeZO/uvfyWKWasmrSrgRB0GuFECR0livsQ+qpqh6zR4CP4juCil7teiceBwhYyG9Gc/5E6FGyp71PlDF1OP+sx7rdhyS/o9LqFQS7meOLdJ3+3AcvTCs92cXH4uLFKkT0k06vHb9eH6uHN6jogx4JNDY5Dfq8Cv+avLMsf484FPzEUzeOPaVBBySyClh0MNxcVrdC2eud+C9LoKuSz6PdJnHxT650MMTVun6m6+tvbfgItu7jPXrSXDEPTDz7AwfUtLnAqzPBlodtjlMM046jHqe+r7MoenZBJ5Y+p+6LZ6exbGY5XlwJQbUCFjth9UTVJTqGNOM+g2U5Vd6bl3+XJHapQRZxNe3BwutG9sgY4itxEdUxEcKvGwp2zk8LXX32job/a/C4amJE1SokhBJIi4k956LApXOY1WGm3zW8jrjae6cXOM0C2nAfM8PEwA+5/XONUVRHJ0M6xq6/m+NrCZZ13dmKOCqZ/9BEsfStrnk28TLXfi6WhXkpOXfNjJbWAuvYoLRFRs/kaXztVoTcilH42rmqShamWWX0rRsLU80kFBodUjzZBQ76mxf3V9cXY1Pd8FZiadE2YpBOvIxEO7CUup6JfHdnwhqMGYQreDbWFcmwnkThWEhTLH+V+ooaIrjmiSRd4IoV9ayOT8Z4g59EEMkkuj05JNwFn1DRhbhVVy4fDGzVOMlHqWYHHGhv3jg+HTskzohNOnsJb+qzQwjT2SR8QIYRepVl071anCeMZ0d3ABZyMT1I0zusORfONjGSsrKLKSC3GdTbo6qmbJCT2Os8L6W9dM1z61z2UkdD4hWBFI2Dijd5MYCn7Ybecb3X3r2Wi53luCXX2jX944Smrlyeg9dUEh38Pi+MxHeszu70anjmCsgiK2Ezb/ioNVE2jlf3eBZMrliXk5p/Qm0nl68iQg2jc4ttjel8r9DnNmEdJfIgGoyy/Ed81qLulbwlxADT7CXi/AjtU5I5i3gdfyJKu8Vd7WcDcfZPluGwEfs3PjwS39vRzR6iwlF6sKooxwAla5Zy10QTV0UXuRqUDQEFhTKMhrDduoo9CWShZEiRPDUkX500yTYJWRYE53zDeyWg8Ge7fhHJPg6Fy7FI4l+YKyqwc0zJy10h3NSKa6KO8VgwzLNmbNSOoTBXlHfy9vfYfAtka+mMYN3KuTfmo+tX8Kc7CCI4DhOP8MhdQDq3ha1rBljI+fv0KTzPZACljp/l/ExXTV84hjsceTpCiJzsX29TTCrcGcKwuOv+aHv/UzR/WbbXTfHOJVfLGFWehUhiHus47pDmAnzwxGpw2BFI24oSogrl0iZ8aWuFFZlH9PQyIyLOtbQUkynEpRMoae+lkzVxKjAYzly4KJmn9b9jQwIcybHT9rHNsv/2VN22JQyBsYBvXekrccbSymDV8L81QJohJqx/UnOtg7aXfF3NPrZqLTuOWekDCvQPpRmDYktn9dEMQ85YFD9WqyTzKIz1zRFp3cw4ymmlPIwhj1Iy/+yqSOdJGo6HCsLgq+DwETCV9R5/KCB4X/89bMvH5FA7Jg0sjCAyotZ9LgT5o2vCpGJkoSCNDT58iQP66TI7xY2wzDqTKW6ic8NmrcIOPhFko1F3wFx/UyzTSjHuLvgy/tVdbcxhWfSB+b7puFq67dvTHNmlpDcCkoqdITgq3c3O4EyMSzQtCdNUUkGp0dkQ1Joi/HH+WpO7eOq5Rw3hiInU0fj6TPPDFC0UJf9QJL/Q/QQPeYxWl4g6FL1vjIAO2xKrKOcto29SRFElTWYXb4L7Z99KNin53tQuMEhPf+ck9T/BMUzQiB2Yhxp2BH5fSI3TUSRSIm+XbXZgwqTfbdOdoCv1fhYfxo4k7Vh5Mk/eFxGEURxw+QTC8Wt6iVEEahmMUVVXJbaXPX/by4bkg2s+FNzdOm2OqiKjQGCoPEF17vSJ/lRwUJIWMzKhNazluffDKslCJUMtz4SGF4bq6v8koNYAmyG0+QsgrGXJDAytJP4jLO8zIuG+NFp++HWG8Q=="; ENCMSGS[89] = "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"; ENCMSGS[90] = "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"; ENCMSGS[91] = "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"; ENCMSGS[92] = "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"; ENCMSGS[93] = "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"; ENCMSGS[94] = "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"; ENCMSGS[95] = "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"; ENCMSGS[96] = "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"; ENCMSGS[97] = "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"; ENCMSGS[98] = "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"; ENCMSGS[99] = "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"; // final FixedStringSaltGenerator saltGenerator = new FixedStringSaltGenerator(); // saltGenerator.setSalt(fixedSalt); // // final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // encryptor.setPassword(encPass); // encryptor.setSaltGenerator(saltGenerator); // // for (int i = 0; i < 100; i++) { // System.out.println( // " ENCMSGS[" + i + "] = \"" + StringEscapeUtils.escapeJava(encryptor.encrypt(MSGS[i])) + "\";"); // } } public void testCompatibility() throws Exception { initMSGS(); initENCMSGS(); final FixedStringSaltGenerator saltGenerator = new FixedStringSaltGenerator(); saltGenerator.setSalt(fixedSalt); final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(encPass); encryptor.setSaltGenerator(saltGenerator); for (int times = 0; times < 100; times++) { for (int i = 0; i < 100; i++) { final String enc = encryptor.encrypt(MSGS[i]); Assert.assertEquals(ENCMSGS[i], enc); } for (int i = 0; i < 100; i++) { final String dec = encryptor.decrypt(ENCMSGS[i]); Assert.assertEquals(MSGS[i], dec); } } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/normalization/000077500000000000000000000000001360667575700253645ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/normalization/NormalizationTest.java000066400000000000000000000041611360667575700317170ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.normalization; import junit.framework.Assert; import junit.framework.TestCase; public class NormalizationTest extends TestCase { public void testNormalizationEquivalence() throws Exception { org.jasypt.normalization.Normalizer.initializeIcu4j(); boolean executeJavaTextNorm = true; try { // Tests might not be executed in Java >= 6 org.jasypt.normalization.Normalizer.initializeJavaTextNormalizer(); } catch (final Exception e) { executeJavaTextNorm = false; } final String msg = "ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÂÊÎÔÛÑÇÆÅßÐáéíóúàèìòùäëïöüâêîôûnçæåÞØÕÃāăþőŏœűŁňć"; final char[] msgCharArray = msg.toCharArray(); String norm1 = com.ibm.icu.text.Normalizer.normalize(msg, com.ibm.icu.text.Normalizer.NFC); String norm2 = new String(org.jasypt.normalization.Normalizer.normalizeWithIcu4j(msgCharArray)); String norm3 = (executeJavaTextNorm? new String(org.jasypt.normalization.Normalizer.normalizeWithJavaNormalizer(msgCharArray)) : null); Assert.assertEquals(norm1, norm2); if (executeJavaTextNorm) { Assert.assertEquals(norm2, norm3); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/properties/000077500000000000000000000000001360667575700246725ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/properties/EncryptablePropertiesTest.java000066400000000000000000000074161360667575700327320ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.properties; import java.util.Properties; import junit.framework.Assert; import junit.framework.TestCase; import org.apache.commons.lang.SerializationUtils; import org.jasypt.util.text.BasicTextEncryptor; public class EncryptablePropertiesTest extends TestCase { public void testEncryptableProperties() throws Exception { final BasicTextEncryptor encryptor = new BasicTextEncryptor(); encryptor.setPassword("jasypt"); final Properties props = new EncryptableProperties(encryptor); props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("props.properties")); final String value = "Spain"; final String locationPlain1 = props.getProperty("location.plain"); final String locationPlain2 = props.getProperty("location.plain", "defaultPlain"); final String locationPlain3 = (String) props.get("location.plain"); final String locationEnc1 = props.getProperty("location.enc"); final String locationEnc2 = props.getProperty("location.enc", "defaultEnc"); final String locationEnc3 = (String) props.get("location.enc"); final String nonExisting1 = props.getProperty("non.existing"); final String nonExisting2 = props.getProperty("non.existing", "defaultNon"); final String nonExisting3 = (String) props.get("non.existing"); Assert.assertEquals(value, locationPlain1); Assert.assertEquals(value, locationPlain2); Assert.assertEquals(value, locationPlain3); Assert.assertEquals(value, locationEnc1); Assert.assertEquals(value, locationEnc2); Assert.assertEquals(value, locationEnc3); Assert.assertNull(nonExisting1); Assert.assertEquals("defaultNon", nonExisting2); Assert.assertNull(nonExisting3); } public void testEncryptablePropertiesSerialization() throws Exception { final BasicTextEncryptor enc01 = new BasicTextEncryptor(); enc01.setPassword("jasypt"); final String msg01 = "Message one"; final String msgEnc01 = "ENC(eZpONwIfFb5muu5Dc8ABsTPu/0OP95p4)"; final String msg02 = "Message two"; final String msgEnc02 = "ENC(LKyQ65EYz3+ekDPpnLjLGyPK07Gt+UZH)"; final EncryptableProperties prop01 = new EncryptableProperties(enc01); prop01.setProperty("p1", msgEnc01); prop01.setProperty("p2", msgEnc02); Assert.assertEquals(prop01.getProperty("p1"), msg01); Assert.assertEquals(prop01.getProperty("p2"), msg02); final byte[] ser01 = SerializationUtils.serialize(prop01); final EncryptableProperties prop02 = (EncryptableProperties) SerializationUtils.deserialize(ser01); Assert.assertEquals(prop02.getProperty("p1"), msg01); Assert.assertEquals(prop02.getProperty("p2"), msg02); Assert.assertNotSame(prop01, prop02); } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/000077500000000000000000000000001360667575700234535ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/binary/000077500000000000000000000000001360667575700247375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/binary/BasicBinaryEncryptorTest.java000066400000000000000000000040151360667575700325360ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; import java.util.Arrays; import junit.framework.TestCase; public class BasicBinaryEncryptorTest extends TestCase { public void testEncrypt() throws Exception { byte[] message = "This is a Message".getBytes(); String password = "APASSWORD"; BasicBinaryEncryptor textEncryptor = new BasicBinaryEncryptor(); textEncryptor.setPassword(password); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = textEncryptor.encrypt(message); assertTrue(Arrays.equals(textEncryptor.decrypt(encryptedMessage), message)); } BasicBinaryEncryptor textEncryptor2 = new BasicBinaryEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = textEncryptor.encrypt(message); assertTrue(Arrays.equals(textEncryptor2.decrypt(encryptedMessage), message)); } for (int i = 0; i < 100; i++) { assertFalse(Arrays.equals( textEncryptor.encrypt(message), textEncryptor.encrypt(message))); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/binary/StrongBinaryEncryptorTest.java000066400000000000000000000040221360667575700327670ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.binary; import java.util.Arrays; import junit.framework.TestCase; public class StrongBinaryEncryptorTest extends TestCase { public void testEncrypt() throws Exception { byte[] message = "This is a Message".getBytes(); String password = "APASSWORD"; StrongBinaryEncryptor textEncryptor = new StrongBinaryEncryptor(); textEncryptor.setPassword(password); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = textEncryptor.encrypt(message); assertTrue(Arrays.equals(textEncryptor.decrypt(encryptedMessage), message)); } StrongBinaryEncryptor textEncryptor2 = new StrongBinaryEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { byte[] encryptedMessage = textEncryptor.encrypt(message); assertTrue(Arrays.equals(textEncryptor2.decrypt(encryptedMessage), message)); } for (int i = 0; i < 100; i++) { assertFalse(Arrays.equals( textEncryptor.encrypt(message), textEncryptor.encrypt(message))); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/digest/000077500000000000000000000000001360667575700247325ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/digest/MessageDigesterTest.java000066400000000000000000000051721360667575700315150ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.digest; import java.security.MessageDigest; import junit.framework.TestCase; import org.apache.commons.lang.ArrayUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class MessageDigesterTest extends TestCase { public void testDigest() throws Exception { byte[] message = "This is a Message".getBytes("UTF-8"); Digester messageDigester = new Digester(); byte[] encryptedMessage = messageDigester.digest(message); MessageDigest md = MessageDigest.getInstance("MD5"); for (int i = 0; i < 100; i++) { assertTrue(ArrayUtils.isEquals(md.digest(message), encryptedMessage)); } byte[] message2 = "This is a Message".getBytes("UTF-8"); for (int i = 0; i < 100; i++) { assertFalse(ArrayUtils.isEquals(md.digest(message2), encryptedMessage)); } Digester messageDigester2 = new Digester(); messageDigester2.setAlgorithm("SHA-1"); byte[] encryptedMessage2 = messageDigester2.digest(message); MessageDigest md2 = MessageDigest.getInstance("SHA-1"); for (int i = 0; i < 100; i++) { assertTrue(ArrayUtils.isEquals(md2.digest(message), encryptedMessage2)); } Digester messageDigester3 = new Digester(); messageDigester3.setAlgorithm("WHIRLPOOL"); messageDigester3.setProvider(new BouncyCastleProvider()); byte[] encryptedMessage3 = messageDigester3.digest(message); MessageDigest md3 = MessageDigest.getInstance("WHIRLPOOL", new BouncyCastleProvider()); for (int i = 0; i < 100; i++) { assertTrue(ArrayUtils.isEquals(md3.digest(message), encryptedMessage3)); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/numeric/000077500000000000000000000000001360667575700251155ustar00rootroot00000000000000BasicDecimalNumberEncryptorTest.java000066400000000000000000000040321360667575700341170ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/numeric/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigDecimal; import junit.framework.TestCase; public class BasicDecimalNumberEncryptorTest extends TestCase { public void testEncrypt() throws Exception { BigDecimal message = BigDecimal.valueOf(-12321318473812923.2131928700009987123); String password = "A PASSWORD1234"; BasicDecimalNumberEncryptor encryptor = new BasicDecimalNumberEncryptor(); encryptor.setPassword(password); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); assertTrue(encryptor.decrypt(encryptedMessage).equals(message)); } BasicDecimalNumberEncryptor textEncryptor2 = new BasicDecimalNumberEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); assertTrue(textEncryptor2.decrypt(encryptedMessage).equals(message)); } for (int i = 0; i < 100; i++) { assertFalse(encryptor.encrypt(message).equals( encryptor.encrypt(message))); } } } BasicIntegerNumberEncryptorTest.java000066400000000000000000000040071360667575700341600ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/numeric/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigInteger; import junit.framework.TestCase; public class BasicIntegerNumberEncryptorTest extends TestCase { public void testEncrypt() throws Exception { BigInteger message = BigInteger.valueOf(-12321318473812923L); String password = "A PASSWORD1234"; BasicIntegerNumberEncryptor encryptor = new BasicIntegerNumberEncryptor(); encryptor.setPassword(password); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); assertTrue(encryptor.decrypt(encryptedMessage).equals(message)); } BasicIntegerNumberEncryptor textEncryptor2 = new BasicIntegerNumberEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); assertTrue(textEncryptor2.decrypt(encryptedMessage).equals(message)); } for (int i = 0; i < 100; i++) { assertFalse(encryptor.encrypt(message).equals( encryptor.encrypt(message))); } } } StrongDecimalNumberEncryptorTest.java000066400000000000000000000040371360667575700343570ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/numeric/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigDecimal; import junit.framework.TestCase; public class StrongDecimalNumberEncryptorTest extends TestCase { public void testEncrypt() throws Exception { BigDecimal message = BigDecimal.valueOf(-12321318473812923.2131928700009987123); String password = "A PASSWORD1234"; StrongDecimalNumberEncryptor encryptor = new StrongDecimalNumberEncryptor(); encryptor.setPassword(password); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); assertTrue(encryptor.decrypt(encryptedMessage).equals(message)); } StrongDecimalNumberEncryptor textEncryptor2 = new StrongDecimalNumberEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { BigDecimal encryptedMessage = encryptor.encrypt(message); assertTrue(textEncryptor2.decrypt(encryptedMessage).equals(message)); } for (int i = 0; i < 100; i++) { assertFalse(encryptor.encrypt(message).equals( encryptor.encrypt(message))); } } } StrongIntegerNumberEncryptorTest.java000066400000000000000000000040141360667575700344110ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/numeric/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.numeric; import java.math.BigInteger; import junit.framework.TestCase; public class StrongIntegerNumberEncryptorTest extends TestCase { public void testEncrypt() throws Exception { BigInteger message = BigInteger.valueOf(-12321318473812923L); String password = "A PASSWORD1234"; StrongIntegerNumberEncryptor encryptor = new StrongIntegerNumberEncryptor(); encryptor.setPassword(password); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); assertTrue(encryptor.decrypt(encryptedMessage).equals(message)); } StrongIntegerNumberEncryptor textEncryptor2 = new StrongIntegerNumberEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { BigInteger encryptedMessage = encryptor.encrypt(message); assertTrue(textEncryptor2.decrypt(encryptedMessage).equals(message)); } for (int i = 0; i < 100; i++) { assertFalse(encryptor.encrypt(message).equals( encryptor.encrypt(message))); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/password/000077500000000000000000000000001360667575700253155ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/password/BasicPasswordEncryptorTest.java000066400000000000000000000046611360667575700335010ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import junit.framework.TestCase; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; public class BasicPasswordEncryptorTest extends TestCase { public void testDigest() throws Exception { String password = "This is a Password"; BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(password); assertTrue(Base64.isArrayByteBase64(encryptedPassword.getBytes("US-ASCII"))); for (int i = 0; i < 100; i++) { assertTrue(passwordEncryptor.checkPassword(password, encryptedPassword)); } String password2 = "This is a Password"; for (int i = 0; i < 100; i++) { assertFalse(passwordEncryptor.checkPassword(password2, encryptedPassword)); } BasicPasswordEncryptor digester2 = new BasicPasswordEncryptor(); for (int i = 0; i < 100; i++) { assertTrue(digester2.checkPassword(password, encryptedPassword)); } for (int i = 0; i < 100; i++) { assertFalse( passwordEncryptor.encryptPassword(password).equals( passwordEncryptor.encryptPassword(password))); } BasicPasswordEncryptor digester3 = new BasicPasswordEncryptor(); encryptedPassword = digester3.encryptPassword(password); for (int i = 0; i < 100; i++) { assertTrue(digester3.checkPassword(password, encryptedPassword)); } } } ConfigurablePasswordEncryptorTest.java000066400000000000000000000054751360667575700350050ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/password/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import java.security.Security; import junit.framework.TestCase; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; public class ConfigurablePasswordEncryptorTest extends TestCase { public void testDigest() throws Exception { String password = "This is a Password"; ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor(); passwordEncryptor.setAlgorithm("WHIRLPOOL"); passwordEncryptor.setProvider(new BouncyCastleProvider()); String encryptedPassword = passwordEncryptor.encryptPassword(password); assertTrue(Base64.isArrayByteBase64(encryptedPassword.getBytes("US-ASCII"))); for (int i = 0; i < 10; i++) { assertTrue(passwordEncryptor.checkPassword(password, encryptedPassword)); } String password2 = "This is a Password"; for (int i = 0; i < 10; i++) { assertFalse(passwordEncryptor.checkPassword(password2, encryptedPassword)); } ConfigurablePasswordEncryptor digester2 = new ConfigurablePasswordEncryptor(); digester2.setAlgorithm("WHIRLPOOL"); Security.addProvider(new BouncyCastleProvider()); digester2.setProviderName("BC"); for (int i = 0; i < 10; i++) { assertTrue(digester2.checkPassword(password, encryptedPassword)); } for (int i = 0; i < 10; i++) { assertFalse( passwordEncryptor.encryptPassword(password).equals( passwordEncryptor.encryptPassword(password))); } StrongPasswordEncryptor digester3 = new StrongPasswordEncryptor(); encryptedPassword = digester3.encryptPassword(password); for (int i = 0; i < 10; i++) { assertTrue(digester3.checkPassword(password, encryptedPassword)); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/password/StrongPasswordEncryptorTest.java000066400000000000000000000046531360667575700337350ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.password; import junit.framework.TestCase; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; public class StrongPasswordEncryptorTest extends TestCase { public void testDigest() throws Exception { String password = "This is a Password"; StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(password); assertTrue(Base64.isArrayByteBase64(encryptedPassword.getBytes("US-ASCII"))); for (int i = 0; i < 10; i++) { assertTrue(passwordEncryptor.checkPassword(password, encryptedPassword)); } String password2 = "This is a Password"; for (int i = 0; i < 10; i++) { assertFalse(passwordEncryptor.checkPassword(password2, encryptedPassword)); } StrongPasswordEncryptor digester2 = new StrongPasswordEncryptor(); for (int i = 0; i < 10; i++) { assertTrue(digester2.checkPassword(password, encryptedPassword)); } for (int i = 0; i < 10; i++) { assertFalse( passwordEncryptor.encryptPassword(password).equals( passwordEncryptor.encryptPassword(password))); } StrongPasswordEncryptor digester3 = new StrongPasswordEncryptor(); encryptedPassword = digester3.encryptPassword(password); for (int i = 0; i < 10; i++) { assertTrue(digester3.checkPassword(password, encryptedPassword)); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/text/000077500000000000000000000000001360667575700244375ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/text/BasicTextEncryptorTest.java000066400000000000000000000042651360667575700317450ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; import junit.framework.TestCase; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; public class BasicTextEncryptorTest extends TestCase { public void testEncrypt() throws Exception { String message = "This is a Message"; String password = "APASSWORD"; BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); textEncryptor.setPassword(password); for (int i = 0; i < 100; i++) { String encryptedMessage = textEncryptor.encrypt(message); assertTrue(Base64.isArrayByteBase64(encryptedMessage.getBytes("US-ASCII"))); assertEquals(textEncryptor.decrypt(encryptedMessage), message); } BasicTextEncryptor textEncryptor2 = new BasicTextEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { String encryptedMessage = textEncryptor.encrypt(message); assertTrue(Base64.isArrayByteBase64(encryptedMessage.getBytes("US-ASCII"))); assertEquals(textEncryptor2.decrypt(encryptedMessage), message); } for (int i = 0; i < 100; i++) { assertFalse( textEncryptor.encrypt(message).equals( textEncryptor.encrypt(message))); } } } jasypt-jasypt-1.9.3/jasypt/src/test/java/org/jasypt/util/text/StrongTextEncryptorTest.java000066400000000000000000000042721360667575700321760ustar00rootroot00000000000000/* * ============================================================================= * * Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org) * * 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. * * ============================================================================= */ package org.jasypt.util.text; import junit.framework.TestCase; import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; public class StrongTextEncryptorTest extends TestCase { public void testEncrypt() throws Exception { String message = "This is a Message"; String password = "APASSWORD"; StrongTextEncryptor textEncryptor = new StrongTextEncryptor(); textEncryptor.setPassword(password); for (int i = 0; i < 100; i++) { String encryptedMessage = textEncryptor.encrypt(message); assertTrue(Base64.isArrayByteBase64(encryptedMessage.getBytes("US-ASCII"))); assertEquals(textEncryptor.decrypt(encryptedMessage), message); } StrongTextEncryptor textEncryptor2 = new StrongTextEncryptor(); textEncryptor2.setPassword(password); for (int i = 0; i < 100; i++) { String encryptedMessage = textEncryptor.encrypt(message); assertTrue(Base64.isArrayByteBase64(encryptedMessage.getBytes("US-ASCII"))); assertEquals(textEncryptor2.decrypt(encryptedMessage), message); } for (int i = 0; i < 100; i++) { assertFalse( textEncryptor.encrypt(message).equals( textEncryptor.encrypt(message))); } } } jasypt-jasypt-1.9.3/jasypt/src/test/resources/000077500000000000000000000000001360667575700214665ustar00rootroot00000000000000jasypt-jasypt-1.9.3/jasypt/src/test/resources/props.properties000066400000000000000000000001041360667575700247420ustar00rootroot00000000000000location.enc=ENC(v0z0uGQRucwfBau0e+gB6A\=\=) location.plain=Spain