From 3a9b8c84683c35460334d6890ba7f5d82d80a828 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 17 May 2022 01:56:44 +0300 Subject: [PATCH] init --- .github/release-drafter.yml | 14 + .github/workflows/build.yml | 39 +++ .github/workflows/release.yml | 42 +++ .github/workflows/test.yml | 32 ++ .gitignore | 10 + LICENSE | 389 +++++++++++++++++++++++ README.md | 22 ++ build/base.go | 393 ++++++++++++++++++++++++ build/base_test.go | 37 +++ build/chrome.go | 178 +++++++++++ build/edge.go | 122 ++++++++ build/file.go | 326 ++++++++++++++++++++ build/file_test.go | 65 ++++ build/firefox.go | 228 ++++++++++++++ build/opera.go | 128 ++++++++ build/testfile.tar.gz | Bin 0 -> 306 bytes build/testfile.zip | Bin 0 -> 178 bytes build/yandex.go | 117 +++++++ ci/build.sh | 8 + ci/docs.sh | 35 +++ ci/test.sh | 4 + cmd/chrome.go | 28 ++ cmd/edge.go | 28 ++ cmd/firefox.go | 36 +++ cmd/opera.go | 28 ++ cmd/root.go | 65 ++++ cmd/version.go | 22 ++ cmd/yandex.go | 28 ++ docs/android.adoc | 44 +++ docs/building-images.adoc | 156 ++++++++++ docs/cdtp.adoc | 16 + docs/chrome-mobile.adoc | 40 +++ docs/chrome.adoc | 67 ++++ docs/cypress.adoc | 219 +++++++++++++ docs/docinfo-footer.html | 26 ++ docs/docinfo.html | 11 + docs/features.adoc | 26 ++ docs/firefox.adoc | 119 +++++++ docs/img/favicon.png | Bin 0 -> 1908 bytes docs/img/og-image.jpg | Bin 0 -> 117092 bytes docs/index.adoc | 37 +++ docs/msedge.adoc | 23 ++ docs/opera.adoc | 83 +++++ docs/playwright.adoc | 195 ++++++++++++ docs/safari.adoc | 12 + docs/windows.adoc | 4 + go.mod | 20 ++ go.sum | 317 +++++++++++++++++++ main.go | 11 + selenium/android/.gitignore | 3 + selenium/android/Dockerfile | 93 ++++++ selenium/android/Emulator.conf | 2 + selenium/android/android.conf | 2 + selenium/android/emulator-snapshot.sh | 16 + selenium/android/entrypoint.sh | 88 ++++++ selenium/android/fluxbox/aerokube | 175 +++++++++++ selenium/android/fluxbox/aerokube.png | Bin 0 -> 127633 bytes selenium/android/fluxbox/init | 7 + selenium/automate_android.sh | 251 +++++++++++++++ selenium/barrier/main.go | 121 ++++++++ selenium/base/Dockerfile | 79 +++++ selenium/base/aerokube.png | Bin 0 -> 127633 bytes selenium/base/fileserver/go.mod | 5 + selenium/base/fileserver/go.sum | 2 + selenium/base/fileserver/main.go | 84 +++++ selenium/base/fileserver/main_test.go | 58 ++++ selenium/base/fluxbox/aerokube | 175 +++++++++++ selenium/base/fluxbox/init | 7 + selenium/base/xseld/go.mod | 3 + selenium/base/xseld/main.go | 44 +++ selenium/external-host/Dockerfile | 28 ++ selenium/external-host/README.md | 16 + selenium/external-host/choose/main.go | 30 ++ selenium/external-host/entrypoint.sh | 51 +++ selenium/external-host/rproxy/main.go | 17 + selenium/opera_presto/Dockerfile | 16 + selenium/opera_presto/entrypoint.sh | 54 ++++ selenium/phantomjs/Dockerfile | 3 + selenium/util/README.md | 10 + selenium/util/rebuild-deb.sh | 94 ++++++ selenium/video/APKBUILD | 76 +++++ selenium/video/Dockerfile | 21 ++ selenium/video/entrypoint.sh | 42 +++ static/chrome/Dockerfile | 25 ++ static/chrome/apt/Dockerfile | 18 ++ static/chrome/devtools/.gitignore | 1 + static/chrome/devtools/devtools.go | 187 +++++++++++ static/chrome/devtools/devtools_test.go | 176 +++++++++++ static/chrome/devtools/go.mod | 12 + static/chrome/devtools/go.sum | 12 + static/chrome/devtools/main.go | 23 ++ static/chrome/entrypoint.sh | 93 ++++++ static/chrome/local/Dockerfile | 62 ++++ static/edge/Dockerfile | 12 + static/edge/apt/Dockerfile | 21 ++ static/edge/entrypoint.sh | 86 ++++++ static/edge/local/Dockerfile | 47 +++ static/firefox/apt/Dockerfile | 20 ++ static/firefox/local/Dockerfile | 36 +++ static/firefox/selenium/Dockerfile | 16 + static/firefox/selenium/entrypoint.sh | 53 ++++ static/firefox/selenoid/Dockerfile | 12 + static/firefox/selenoid/browsers.json | 10 + static/firefox/selenoid/entrypoint.sh | 94 ++++++ static/opera/Dockerfile | 11 + static/opera/apt/Dockerfile | 16 + static/opera/entrypoint.sh | 85 +++++ static/opera/local/Dockerfile | 62 ++++ static/safari/.gitignore | 1 + static/safari/Dockerfile | 64 ++++ static/safari/cmd/prism/go.mod | 3 + static/safari/cmd/prism/main.go | 150 +++++++++ static/safari/entrypoint.sh | 74 +++++ static/yandex/Dockerfile | 11 + static/yandex/apt/Dockerfile | 14 + static/yandex/entrypoint.sh | 85 +++++ static/yandex/local/Dockerfile | 60 ++++ 117 files changed, 7175 insertions(+) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 build/base.go create mode 100644 build/base_test.go create mode 100644 build/chrome.go create mode 100644 build/edge.go create mode 100644 build/file.go create mode 100644 build/file_test.go create mode 100644 build/firefox.go create mode 100644 build/opera.go create mode 100644 build/testfile.tar.gz create mode 100644 build/testfile.zip create mode 100644 build/yandex.go create mode 100755 ci/build.sh create mode 100755 ci/docs.sh create mode 100755 ci/test.sh create mode 100644 cmd/chrome.go create mode 100644 cmd/edge.go create mode 100644 cmd/firefox.go create mode 100644 cmd/opera.go create mode 100644 cmd/root.go create mode 100644 cmd/version.go create mode 100644 cmd/yandex.go create mode 100644 docs/android.adoc create mode 100644 docs/building-images.adoc create mode 100644 docs/cdtp.adoc create mode 100644 docs/chrome-mobile.adoc create mode 100644 docs/chrome.adoc create mode 100644 docs/cypress.adoc create mode 100644 docs/docinfo-footer.html create mode 100644 docs/docinfo.html create mode 100644 docs/features.adoc create mode 100644 docs/firefox.adoc create mode 100644 docs/img/favicon.png create mode 100644 docs/img/og-image.jpg create mode 100644 docs/index.adoc create mode 100644 docs/msedge.adoc create mode 100644 docs/opera.adoc create mode 100644 docs/playwright.adoc create mode 100644 docs/safari.adoc create mode 100644 docs/windows.adoc create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 selenium/android/.gitignore create mode 100644 selenium/android/Dockerfile create mode 100644 selenium/android/Emulator.conf create mode 100644 selenium/android/android.conf create mode 100755 selenium/android/emulator-snapshot.sh create mode 100755 selenium/android/entrypoint.sh create mode 100644 selenium/android/fluxbox/aerokube create mode 100644 selenium/android/fluxbox/aerokube.png create mode 100644 selenium/android/fluxbox/init create mode 100755 selenium/automate_android.sh create mode 100644 selenium/barrier/main.go create mode 100644 selenium/base/Dockerfile create mode 100644 selenium/base/aerokube.png create mode 100644 selenium/base/fileserver/go.mod create mode 100644 selenium/base/fileserver/go.sum create mode 100644 selenium/base/fileserver/main.go create mode 100644 selenium/base/fileserver/main_test.go create mode 100644 selenium/base/fluxbox/aerokube create mode 100644 selenium/base/fluxbox/init create mode 100644 selenium/base/xseld/go.mod create mode 100644 selenium/base/xseld/main.go create mode 100644 selenium/external-host/Dockerfile create mode 100644 selenium/external-host/README.md create mode 100644 selenium/external-host/choose/main.go create mode 100755 selenium/external-host/entrypoint.sh create mode 100644 selenium/external-host/rproxy/main.go create mode 100644 selenium/opera_presto/Dockerfile create mode 100755 selenium/opera_presto/entrypoint.sh create mode 100644 selenium/phantomjs/Dockerfile create mode 100644 selenium/util/README.md create mode 100755 selenium/util/rebuild-deb.sh create mode 100644 selenium/video/APKBUILD create mode 100644 selenium/video/Dockerfile create mode 100755 selenium/video/entrypoint.sh create mode 100644 static/chrome/Dockerfile create mode 100644 static/chrome/apt/Dockerfile create mode 100644 static/chrome/devtools/.gitignore create mode 100644 static/chrome/devtools/devtools.go create mode 100644 static/chrome/devtools/devtools_test.go create mode 100644 static/chrome/devtools/go.mod create mode 100644 static/chrome/devtools/go.sum create mode 100644 static/chrome/devtools/main.go create mode 100755 static/chrome/entrypoint.sh create mode 100644 static/chrome/local/Dockerfile create mode 100644 static/edge/Dockerfile create mode 100644 static/edge/apt/Dockerfile create mode 100755 static/edge/entrypoint.sh create mode 100644 static/edge/local/Dockerfile create mode 100644 static/firefox/apt/Dockerfile create mode 100644 static/firefox/local/Dockerfile create mode 100644 static/firefox/selenium/Dockerfile create mode 100755 static/firefox/selenium/entrypoint.sh create mode 100644 static/firefox/selenoid/Dockerfile create mode 100644 static/firefox/selenoid/browsers.json create mode 100755 static/firefox/selenoid/entrypoint.sh create mode 100644 static/opera/Dockerfile create mode 100644 static/opera/apt/Dockerfile create mode 100755 static/opera/entrypoint.sh create mode 100644 static/opera/local/Dockerfile create mode 100644 static/safari/.gitignore create mode 100644 static/safari/Dockerfile create mode 100644 static/safari/cmd/prism/go.mod create mode 100644 static/safari/cmd/prism/main.go create mode 100755 static/safari/entrypoint.sh create mode 100644 static/yandex/Dockerfile create mode 100644 static/yandex/apt/Dockerfile create mode 100755 static/yandex/entrypoint.sh create mode 100644 static/yandex/local/Dockerfile diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..27a4fa7 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,14 @@ +name-template: $NEXT_PATCH_VERSION +tag-template: $NEXT_PATCH_VERSION +template: | + ## What’s Changed + + $CHANGES + +categories: + - title: New features + label: new-feature + - title: Fixes + label: bug + - title: Improvements + label: improvement diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9972c37 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,39 @@ +name: build + +on: + push: + branches: + - master + +jobs: + golang: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Golang + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Test + run: ci/test.sh + + - name: Build + run: ci/build.sh + + - name: Latest docs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ci/docs.sh latest ${{ secrets.GITHUB_TOKEN }} + + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2bd0da7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: release + +on: + release: + types: [published] + +jobs: + golang: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Golang + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Test + run: ci/test.sh + + - name: Build + run: ci/build.sh + + - name: Prepare release version + run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV + + - uses: AButler/upload-release-assets@v2.0 + with: + files: 'dist/*' + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Release docs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ci/docs.sh $RELEASE_VERSION ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a5572b6 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +name: test + +on: + pull_request: + +jobs: + golang: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Golang + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Test + run: ci/test.sh + + - name: Build + run: ci/build.sh + + - uses: codecov/codecov-action@v1 + with: + flags: go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f4d6fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.idea +*.deb +*.bak +images +pkged.go + +.DS_Store + +selenium/barrier/barrier diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..422c3c7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,389 @@ +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. + + 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 2017+ Aerokube Software OÜ + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2161fa7 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Browser Images +[![Build Status](https://github.com/aerokube/images/workflows/build/badge.svg)](https://github.com/aerokube/images/actions?query=workflow%3Abuild) +[![Release](https://img.shields.io/github/release/aerokube/images.svg)](https://github.com/aerokube/images/releases/latest) + +This repository contains [Docker](http://docker.com/) build files to be used for [Selenoid](http://github.com/aerokube/selenoid) and [Moon](http://github.com/aerokube/moon) projects. You can find prebuilt images [here](https://hub.docker.com/u/selenoid/). + +## Download Statistics + +### Firefox: [![Firefox Docker Pulls](https://img.shields.io/docker/pulls/selenoid/firefox.svg)](https://hub.docker.com/r/selenoid/firefox) + +### Chrome: [![Chrome Docker Pulls](https://img.shields.io/docker/pulls/selenoid/chrome.svg)](https://hub.docker.com/r/selenoid/chrome) + +### Opera: [![Opera Docker Pulls](https://img.shields.io/docker/pulls/selenoid/opera.svg)](https://hub.docker.com/r/selenoid/opera) + +### Android: [![Android Docker Pulls](https://img.shields.io/docker/pulls/selenoid/android.svg)](https://hub.docker.com/r/selenoid/android) + +## Building Images + +Moved to: http://aerokube.com/images/latest/#_building_images + +## Image information +Moved to: http://aerokube.com/images/latest/#_browser_image_information diff --git a/build/base.go b/build/base.go new file mode 100644 index 0000000..dbabe22 --- /dev/null +++ b/build/base.go @@ -0,0 +1,393 @@ +package build + +import ( + "context" + "errors" + "fmt" + "github.com/markbates/pkger" + "io" + "io/ioutil" + "log" + "net" + "net/http" + "net/url" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "runtime" + "strings" + "time" +) + +const ( + LatestVersion = "latest" +) + +type Requirements struct { + BrowserSource BrowserSource + BrowserChannel string // "beta", "esr", "dev" and so on + DriverVersion string + Tags []string + NoCache bool + TestsDir string + RunTests bool + IgnoreTests bool + PushImage bool +} + +type BrowserSource string + +// Return regular file corresponding to this source and optionally download this file +func (bs *BrowserSource) Prepare() (string, string, error) { + src := string(*bs) + if src == "" { + return "", "", errors.New("empty browser source") + } + if _, err := os.Stat(src); err == nil { + pkgName := filepath.Base(src) + return src, extractVersion(pkgName), nil + } else if u, err := url.Parse(src); strings.HasPrefix(src, "http") && err == nil { + pkgName := path.Base(src) + data, err := downloadFile(u.String()) + if err != nil { + return "", "", fmt.Errorf("download file: %v", err) + } + f, err := ioutil.TempFile("", "images") + if err != nil { + return "", "", fmt.Errorf("temporary file: %v", err) + } + outputFileName := f.Name() + err = ioutil.WriteFile(outputFileName, data, 0644) + if err != nil { + return "", "", fmt.Errorf("save downloaded file: %v", err) + } + return outputFileName, extractVersion(pkgName), nil + } + return "", src, nil +} + +func extractVersion(name string) string { + pieces := strings.Split(name, "_") + version := name + if len(pieces) >= 2 { + version = pieces[1] + } + pieces = strings.Split(version, "+") + pieces = strings.Split(pieces[0], "-") + pieces = strings.Split(pieces[0], "~") + return pieces[0] +} + +func versionN(pkgVersion string, n int) string { + buildVersion := pkgVersion + pieces := strings.Split(pkgVersion, ".") + if len(pieces) >= n { + buildVersion = strings.Join(pieces[0:n], ".") + } + return buildVersion +} + +func majorVersion(pkgVersion string) string { + return versionN(pkgVersion, 1) +} + +func majorMinorVersion(pkgVersion string) string { + return versionN(pkgVersion, 2) +} + +func buildVersion(pkgVersion string) string { + return versionN(pkgVersion, 3) +} + +type Image struct { + Dir string + BuildArgs []string + Labels []string + FileServer bool + Requirements +} + +func NewImage(srcDir string, destDir string, req Requirements) (*Image, error) { + if !requireCommand("docker") { + return nil, fmt.Errorf("docker is not installed") + } + + dir, err := copySourceFiles(srcDir, destDir) + if err != nil { + return nil, fmt.Errorf("copy source files: %v", err) + } + + if len(req.Tags) == 0 { + return nil, errors.New("image tag is required") + } + return &Image{Dir: dir, Requirements: req}, nil +} + +func requireCommand(cmd string) bool { + _, err := exec.LookPath(cmd) + return err == nil +} + +func tmpDir() (string, error) { + dir, err := ioutil.TempDir("", "images") + if err != nil { + return "", fmt.Errorf("create temporary dir: %v", err) + } + return dir, nil +} + +func copySourceFiles(srcDir string, destDir string) (string, error) { + + const prefix = "/static" + walkDir := filepath.Join(prefix, srcDir) + err := pkger.Walk(walkDir, func(path string, info os.FileInfo, err error) error { + + if err != nil { + return err + } + + regex := regexp.MustCompile(`^.+:/static(.+)$`) + relativePath := regex.FindStringSubmatch(path)[1] + outputPath := filepath.Join(destDir, relativePath) + if info.IsDir() { + return os.MkdirAll(outputPath, info.Mode()) + } + + fileDir := filepath.Join(destDir, filepath.Dir(relativePath)) + if !fileExists(fileDir) { + log.Printf("mkdir dir %s", fileDir) + return os.MkdirAll(fileDir, info.Mode()) + } + + src, err := pkger.Open(path) + if err != nil { + return err + } + defer src.Close() + + dest, err := os.Create(outputPath) + if err != nil { + return err + } + defer dest.Close() + + _, err = io.Copy(dest, src) + if err != nil { + return err + } + + err = dest.Sync() + if err != nil { + return err + } + + err = os.Chmod(outputPath, info.Mode()) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + return "", err + } + + return filepath.Join(destDir, srcDir), nil +} + +func (i *Image) Build() error { + + args := []string{"build"} + for _, tag := range i.Tags { + args = append(args, "-t", tag) + } + if len(i.BuildArgs) > 0 { + for _, arg := range i.BuildArgs { + args = append(args, "--build-arg", arg) + } + } + if httpProxy := os.Getenv("HTTP_PROXY"); httpProxy != "" { + args = append(args, "--build-arg", fmt.Sprintf("http_proxy=%s", httpProxy)) + } + if httpsProxy := os.Getenv("HTTPS_PROXY"); httpsProxy != "" { + args = append(args, "--build-arg", fmt.Sprintf("https_proxy=%s", httpsProxy)) + } + if len(i.Labels) > 0 { + for _, label := range i.Labels { + args = append(args, "--label", label) + } + } + + if i.NoCache { + args = append(args, "--no-cache") + } + + if i.FileServer { + server := &http.Server{ + Handler: http.FileServer(http.Dir(i.Dir)), + } + ln, err := net.Listen("tcp", ":8080") + if err != nil { + return fmt.Errorf("failed to allocate free port: %v", err) + } + + e := make(chan error) + go func() { + e <- server.Serve(ln) + }() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + defer server.Shutdown(ctx) + if runtime.GOOS == "linux" { + ip, err := dockerHostIP() + if err != nil { + return fmt.Errorf("failed to detect host machine IP: %v", err) + } + args = append(args, "--add-host", fmt.Sprintf("host.docker.internal:%s", ip)) + } + } + + args = append(args, i.Dir) + log.Printf("running command: docker %s", strings.Join(args, " ")) + cmd := exec.Command("docker", args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Start() + if err != nil { + return fmt.Errorf("failed to start command: %v", err) + } + err = cmd.Wait() + if err != nil { + return fmt.Errorf("command execution error: %v", err) + } + return nil +} + +func dockerHostIP() (string, error) { + ifaces, err := net.Interfaces() + if err != nil { + return "", err + } + for _, iface := range ifaces { + if iface.Name != "docker0" { + continue + } + if iface.Flags&net.FlagUp == 0 { + continue // interface down + } + if iface.Flags&net.FlagLoopback != 0 { + continue // loopback interface + } + addrs, err := iface.Addrs() + if err != nil { + return "", err + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + continue // not an ipv4 address + } + return ip.String(), nil + } + } + return "", errors.New("no live network interfaces detected") +} + +func (i *Image) Test(testsDir string, browserName string, browserVersion string) error { + if !i.RunTests { + log.Println("not running tests") + return nil + } + ref := i.Tags[0] + err := doTest(ref, testsDir, browserName, browserVersion) + if err != nil { + if i.IgnoreTests { + log.Printf("ignoring tests: %v", err) + return nil + } + return fmt.Errorf("tests error: %v", err) + } + log.Println("tests passed") + return nil +} + +func doTest(ref string, testsDir string, browserName string, browserVersion string) error { + if !fileExists(testsDir) { + return fmt.Errorf("tests directory %s does not exist", testsDir) + } + + seleniumUrl := "http://localhost:4445/" + if browserName == "firefox" || (browserName == "opera" && browserVersion == "12.16") { + seleniumUrl = "http://localhost:4445/wd/hub" + } + + exec.Command("docker", "rm", "-f", "selenium").Output() + defer func() { + exec.Command("docker", "rm", "-f", "selenium").Output() + }() + + output, err := exec.Command("docker", "run", "-d", "--name", "selenium", "--privileged", "-p", "4445:4444", ref).Output() + if err != nil { + return fmt.Errorf("failed to start docker image: %s %v", string(output), err) + } + + if !requireCommand("mvn") { + return fmt.Errorf("maven is not installed") + } + + mvnCmd := exec.Command("mvn", "clean", "test", + fmt.Sprintf("-Dgrid.connection.url=%s", seleniumUrl), + fmt.Sprintf("-Dgrid.browser.name=%s", browserName), + fmt.Sprintf("-Dgrid.browser.version=%s", browserVersion), + ) + mvnCmd.Dir = testsDir + mvnCmd.Stdout = os.Stdout + mvnCmd.Stderr = os.Stderr + err = mvnCmd.Start() + if err != nil { + return fmt.Errorf("failed to start tests: %v", err) + } + err = mvnCmd.Wait() + if err != nil { + return fmt.Errorf("tests finished with error: %v", err) + } + + return nil +} + +func fileExists(p string) bool { + _, err := os.Stat(p) + return !os.IsNotExist(err) +} + +func (i *Image) Push() error { + if i.PushImage { + for _, tag := range i.Tags { + cmd := exec.Command("docker", "push", tag) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Start() + if err != nil { + return fmt.Errorf("invalid docker push %s: %v", tag, err) + } + err = cmd.Wait() + if err != nil { + return fmt.Errorf("pushing failed: %v", err) + } + } + } + return nil +} diff --git a/build/base_test.go b/build/base_test.go new file mode 100644 index 0000000..3dc0797 --- /dev/null +++ b/build/base_test.go @@ -0,0 +1,37 @@ +package build + +import ( + . "github.com/aandryashin/matchers" + "testing" +) + +func TestVersionFromPackageName(t *testing.T) { + AssertThat(t, extractVersion("firefox_45.0.2+build1-0ubuntu0.14.04.1+aerokube0_amd64.deb"), EqualTo{"45.0.2"}) + AssertThat(t, extractVersion("firefox_71.0_b11+build1-0ubuntu0.18.04.1_amd64.deb"), EqualTo{"71.0"}) + AssertThat(t, extractVersion("firefox-trunk_72.0_a1_hg20191114r501767-0ubuntu0.18.04.1_umd1_amd64.deb"), EqualTo{"72.0"}) + AssertThat(t, extractVersion("google-chrome-stable_48.0.2564.109-1+aerokube0_amd64.deb"), EqualTo{"48.0.2564.109"}) + AssertThat(t, extractVersion("google-chrome-beta_79.0.3945.36-1_amd64.deb"), EqualTo{"79.0.3945.36"}) + AssertThat(t, extractVersion("google-chrome-unstable_80.0.3964.0-1_amd64.deb"), EqualTo{"80.0.3964.0"}) + AssertThat(t, extractVersion("opera-stable_38.0.2220.31_amd64.deb"), EqualTo{"38.0.2220.31"}) + AssertThat(t, extractVersion("opera-beta_65.0.3467.32_amd64.deb"), EqualTo{"65.0.3467.32"}) + AssertThat(t, extractVersion("opera-developer_66.0.3502.0_amd64.deb"), EqualTo{"66.0.3502.0"}) + AssertThat(t, extractVersion("yandex-browser-beta_19.9.3.358-1_amd64.deb"), EqualTo{"19.9.3.358"}) +} + +func TestVersionToTag(t *testing.T) { + AssertThat(t, extractVersion("45.0.2+build1-0ubuntu0.14.04.1+aerokube0"), EqualTo{"45.0.2"}) + AssertThat(t, extractVersion("48.0.2564.109-1+aerokube0"), EqualTo{"48.0.2564.109"}) + AssertThat(t, extractVersion("78.0.3904.108-1"), EqualTo{"78.0.3904.108"}) + AssertThat(t, extractVersion("38.0.2220.31"), EqualTo{"38.0.2220.31"}) + AssertThat(t, extractVersion("71.0~b11+build1-0ubuntu0.18.04.1"), EqualTo{"71.0"}) + AssertThat(t, extractVersion("74.0~a1~hg20200205r512485-0ubuntu0.18.04.1~umd1"), EqualTo{"74.0"}) +} + +func TestParseVersion(t *testing.T) { + AssertThat(t, majorVersion("78.0.3904.108"), EqualTo{"78"}) + AssertThat(t, majorVersion("78"), EqualTo{"78"}) + AssertThat(t, majorMinorVersion("78.0.3904.108"), EqualTo{"78.0"}) + AssertThat(t, majorMinorVersion("78.0"), EqualTo{"78.0"}) + AssertThat(t, buildVersion("78.0.3904.108"), EqualTo{"78.0.3904"}) + AssertThat(t, buildVersion("78.0.3904"), EqualTo{"78.0.3904"}) +} diff --git a/build/chrome.go b/build/chrome.go new file mode 100644 index 0000000..d2a3b8c --- /dev/null +++ b/build/chrome.go @@ -0,0 +1,178 @@ +package build + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strconv" +) + +const ( + chromeDriverBinary = "chromedriver" +) + +type Chrome struct { + Requirements +} + +func (c *Chrome) Build() error { + + pkgSrcPath, pkgVersion, err := c.BrowserSource.Prepare() + if err != nil { + return fmt.Errorf("invalid browser source: %v", err) + } + + pkgTagVersion := extractVersion(pkgVersion) + + driverVersion, err := c.parseChromeDriverVersion(pkgTagVersion) + if err != nil { + return fmt.Errorf("parse chromedriver version: %v", err) + } + + // Build dev image + devDestDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create dev temporary dir: %v", err) + } + + srcDir := "chrome/apt" + + if pkgSrcPath != "" { + srcDir = "chrome/local" + pkgDestDir := filepath.Join(devDestDir, srcDir) + err := os.MkdirAll(pkgDestDir, 0755) + if err != nil { + return fmt.Errorf("create %v temporary dir: %v", pkgDestDir, err) + } + pkgDestPath := filepath.Join(pkgDestDir, "google-chrome.deb") + err = os.Rename(pkgSrcPath, pkgDestPath) + if err != nil { + return fmt.Errorf("move package: %v", err) + } + } + + devImageTag := fmt.Sprintf("selenoid/dev_chrome:%s", pkgTagVersion) + devImageRequirements := Requirements{NoCache: c.NoCache, Tags: []string{devImageTag}} + devImage, err := NewImage(srcDir, devDestDir, devImageRequirements) + if err != nil { + return fmt.Errorf("init dev image: %v", err) + } + devBuildArgs := []string{fmt.Sprintf("VERSION=%s", pkgVersion)} + devBuildArgs = append(devBuildArgs, c.channelToBuildArgs()...) + devImage.BuildArgs = devBuildArgs + if pkgSrcPath != "" { + devImage.FileServer = true + } + + err = devImage.Build() + if err != nil { + return fmt.Errorf("build dev image: %v", err) + } + + // Build main image + destDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create temporary dir: %v", err) + } + + image, err := NewImage("chrome", destDir, c.Requirements) + if err != nil { + return fmt.Errorf("init image: %v", err) + } + image.BuildArgs = append(image.BuildArgs, fmt.Sprintf("VERSION=%s", pkgTagVersion)) + + err = c.downloadChromeDriver(image.Dir, driverVersion) + if err != nil { + return fmt.Errorf("failed to download chromedriver: %v", err) + } + image.Labels = []string{fmt.Sprintf("driver=chromedriver:%s", driverVersion)} + + err = image.Build() + if err != nil { + return fmt.Errorf("build image: %v", err) + } + + err = image.Test(c.TestsDir, "chrome", pkgTagVersion) + if err != nil { + return fmt.Errorf("test image: %v", err) + } + + err = image.Push() + if err != nil { + return fmt.Errorf("push image: %v", err) + } + + return nil +} + +func (c *Chrome) channelToBuildArgs() []string { + switch c.BrowserChannel { + case "beta": + return []string{"PACKAGE=google-chrome-beta", "INSTALL_DIR=chrome-beta"} + case "dev": + return []string{"PACKAGE=google-chrome-unstable", "INSTALL_DIR=chrome-unstable"} + default: + return []string{} + } +} + +func (c *Chrome) parseChromeDriverVersion(pkgVersion string) (string, error) { + version := c.DriverVersion + if version == LatestVersion { + const baseUrl = "https://chromedriver.storage.googleapis.com/" + v, err := c.getLatestChromeDriver(baseUrl, pkgVersion) + if err != nil { + return "", err + } + version = v + } + return version, nil +} + +func (c *Chrome) downloadChromeDriver(dir string, version string) error { + u := fmt.Sprintf("http://chromedriver.storage.googleapis.com/%s/chromedriver_linux64.zip", version) + _, err := downloadDriver(u, chromeDriverBinary, dir) + if err != nil { + return fmt.Errorf("download chromedriver: %v", err) + } + return nil +} + +func (c *Chrome) getLatestChromeDriver(baseUrl string, pkgVersion string) (string, error) { + fetchVersion := func(url string) (string, error) { + data, err := sendGet(url) + if err != nil { + return "", fmt.Errorf("read chromedriver version: %v", err) + } + return string(data), nil + } + + if c.BrowserChannel != "dev" { + chromeBuildVersion := buildVersion(pkgVersion) + u := baseUrl + fmt.Sprintf("LATEST_RELEASE_%s", chromeBuildVersion) + v, err := fetchVersion(u) + if err == nil { + return v, nil + } + } + + chromeMajorVersion, err := strconv.Atoi(majorVersion(pkgVersion)) + if err != nil { + return "", fmt.Errorf("chrome major version: %v", err) + } + u := baseUrl + fmt.Sprintf("LATEST_RELEASE_%d", chromeMajorVersion) + v, err := fetchVersion(u) + if err == nil { + return v, nil + } else { + previousChromeMajorVersion := chromeMajorVersion - 1 + u = baseUrl + fmt.Sprintf("LATEST_RELEASE_%d", previousChromeMajorVersion) + v, err := fetchVersion(u) + if err == nil { + return v, nil + } else { + return "", errors.New("could not find compatible chromedriver") + } + } +} diff --git a/build/edge.go b/build/edge.go new file mode 100644 index 0000000..bed05b1 --- /dev/null +++ b/build/edge.go @@ -0,0 +1,122 @@ +package build + +import ( + "fmt" + "os" + "path/filepath" +) + +const ( + msedgeDriverBinary = "msedgedriver" +) + +type Edge struct { + Requirements +} + +func (c *Edge) Build() error { + + pkgSrcPath, pkgVersion, err := c.BrowserSource.Prepare() + if err != nil { + return fmt.Errorf("invalid browser source: %v", err) + } + + pkgTagVersion := extractVersion(pkgVersion) + + // Build dev image + devDestDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create dev temporary dir: %v", err) + } + + srcDir := "edge/apt" + + if pkgSrcPath != "" { + srcDir = "edge/local" + pkgDestDir := filepath.Join(devDestDir, srcDir) + err := os.MkdirAll(pkgDestDir, 0755) + if err != nil { + return fmt.Errorf("create %v temporary dir: %v", pkgDestDir, err) + } + pkgDestPath := filepath.Join(pkgDestDir, "microsoft-edge.deb") + err = os.Rename(pkgSrcPath, pkgDestPath) + if err != nil { + return fmt.Errorf("move package: %v", err) + } + } + + devImageTag := fmt.Sprintf("selenoid/dev_edge:%s", pkgTagVersion) + devImageRequirements := Requirements{NoCache: c.NoCache, Tags: []string{devImageTag}} + devImage, err := NewImage(srcDir, devDestDir, devImageRequirements) + if err != nil { + return fmt.Errorf("init dev image: %v", err) + } + devBuildArgs := []string{fmt.Sprintf("VERSION=%s", pkgVersion)} + devBuildArgs = append(devBuildArgs, c.channelToBuildArgs()...) + devImage.BuildArgs = devBuildArgs + if pkgSrcPath != "" { + devImage.FileServer = true + } + + err = devImage.Build() + if err != nil { + return fmt.Errorf("build dev image: %v", err) + } + + // Build main image + destDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create temporary dir: %v", err) + } + + image, err := NewImage("edge", destDir, c.Requirements) + if err != nil { + return fmt.Errorf("init image: %v", err) + } + image.BuildArgs = append(image.BuildArgs, fmt.Sprintf("VERSION=%s", pkgTagVersion)) + + driverVersion, err := c.downloadMSEdgeDriver(image.Dir) + if err != nil { + return fmt.Errorf("failed to download msedgedriver: %v", err) + } + image.Labels = []string{fmt.Sprintf("driver=msedgedriver:%s", driverVersion)} + + err = image.Build() + if err != nil { + return fmt.Errorf("build image: %v", err) + } + + err = image.Test(c.TestsDir, "MicrosoftEdge", pkgTagVersion) + if err != nil { + return fmt.Errorf("test image: %v", err) + } + + err = image.Push() + if err != nil { + return fmt.Errorf("push image: %v", err) + } + + return nil +} + +func (c *Edge) channelToBuildArgs() []string { + switch c.BrowserChannel { + case "beta": + return []string{"PACKAGE=microsoft-edge-beta", "INSTALL_DIR=msedge-beta"} + case "dev": + return []string{"PACKAGE=microsoft-edge-dev", "INSTALL_DIR=msedge-dev"} + default: + return []string{} + } +} + +func (c *Edge) downloadMSEdgeDriver(dir string) (string, error) { + version := c.DriverVersion + // Full driver versions list can be fetched as XML from https://msedgedriver.azureedge.net/ + u := fmt.Sprintf("https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver/%s/edgedriver_linux64.zip", version) + _, err := downloadDriver(u, msedgeDriverBinary, dir) + if err != nil { + return "", fmt.Errorf("download msedgedriver: %v", err) + } + return version, nil +} diff --git a/build/file.go b/build/file.go new file mode 100644 index 0000000..44e59be --- /dev/null +++ b/build/file.go @@ -0,0 +1,326 @@ +package build + +import ( + "archive/tar" + "archive/zip" + "bufio" + "bytes" + "compress/gzip" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "log" + "math/rand" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "gopkg.in/cheggaaa/pb.v1" +) + +const ( + zipMagicHeader = "504b" + gzipMagicHeader = "1f8b" +) + +func downloadFile(url string) ([]byte, error) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + err := downloadFileWithProgressBar(url, w) + if err != nil { + return nil, err + } + w.Flush() + return b.Bytes(), nil +} + +func downloadFileWithProgressBar(url string, w io.Writer) error { + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("file download error: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + return fmt.Errorf("unexpected response code: %d", resp.StatusCode) + } + + contentLength := int(resp.ContentLength) + writer := w + + if contentLength > 0 { + bar := pb.New(contentLength).SetUnits(pb.U_BYTES) + bar.Output = os.Stderr + bar.Start() + defer bar.Finish() + writer = io.MultiWriter(w, bar) + } + + _, err = io.Copy(writer, resp.Body) + if err != nil { + return fmt.Errorf("failed to save file: %v", err) + } + return nil +} + +func downloadDriver(url string, filename string, outputDir string) (string, error) { + log.Printf("downloading driver from %s", url) + data, err := downloadFile(url) + if err != nil { + return "", fmt.Errorf("failed to download driver archive: %v", err) + } + return extractFile(data, filename, outputDir) +} + +func getMagicHeader(data []byte) string { + if len(data) >= 2 { + return hex.EncodeToString(data[:2]) + } + return "" +} + +func isZipFile(data []byte) bool { + return getMagicHeader(data) == zipMagicHeader +} + +func isTarGzFile(data []byte) bool { + return getMagicHeader(data) == gzipMagicHeader +} + +func extractFile(data []byte, filename string, outputDir string) (string, error) { + if isZipFile(data) { + return unzip(data, filename, outputDir) + } else if isTarGzFile(data) { + return untar(data, filename, outputDir) + } else { + outputPath := filepath.Join(outputDir, filename) + err := ioutil.WriteFile(outputPath, data, os.ModePerm) + if err != nil { + return "", fmt.Errorf("failed to save file %s: %v", outputPath, err) + } + fmt.Println("Patched chromedriver") + patchDriver(outputPath) + return outputPath, nil + } +} + +func patchDriver(filename string) { + rand.Seed(time.Now().UnixNano()) + var lettersLower = []byte("abcdefghijklmnopqrstuvwxyz") + var lettersUpper = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + rand_str_repl := make([]byte, 26) + for i := range rand_str_repl { + if i == 2 { + rand_str_repl[i] = rand_str_repl[0] + } else if i == 3 { + rand_str_repl[i] = byte('_') + } else if i == 20 || i == 21 { + rand_str_repl[i] = lettersUpper[rand.Intn(len(lettersUpper))] + } else { + rand_str_repl[i] = lettersLower[rand.Intn(len(lettersLower))] + } + + } + log.Println(string(rand_str_repl)) + re := regexp.MustCompile(`cdc_.{22}`) + input_file, err := ioutil.ReadFile(filename) + log.Println(filename) + if err == nil { + match := re.Find(input_file) + if match == nil { + log.Fatalln("cant find driver cdc_") + } + log.Println(string(match)) + output_data := re.ReplaceAll(input_file, rand_str_repl) + match = re.Find(output_data) + if match != nil { + log.Fatalln("cant patch driver cdc_") + } + err := ioutil.WriteFile(filename, output_data, os.ModePerm) + if err != nil { + log.Fatalln("cant write to file") + } + + } + +} + +// Based on http://stackoverflow.com/questions/20357223/easy-way-to-unzip-file-with-golang +func unzip(data []byte, fileName string, outputDir string) (string, error) { + zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + + // Closure to address file descriptors issue with all the deferred .Close() methods + extractAndWriteFile := func(f *zip.File) (string, error) { + rc, err := f.Open() + if err != nil { + return "", err + } + defer rc.Close() + + outputPath := filepath.Join(outputDir, f.Name) + + if f.FileInfo().IsDir() { + return "", fmt.Errorf("can only unzip files but %s is a directory", f.Name) + } + + err = outputFile(outputPath, f.Mode(), rc) + if err != nil { + return "", err + } + fmt.Println("Patched chromedriver") + patchDriver(outputPath) + return outputPath, nil + } + + if err == nil { + for _, f := range zr.File { + if f.Name == fileName { + return extractAndWriteFile(f) + } + } + err = fmt.Errorf("file %s does not exist in archive", fileName) + } + + return "", err +} + +// Based on https://medium.com/@skdomino/taring-untaring-files-in-go-6b07cf56bc07 +func untar(data []byte, fileName string, outputDir string) (string, error) { + + gzr, err := gzip.NewReader(bytes.NewReader(data)) + defer gzr.Close() + + extractAndWriteFile := func(tr *tar.Reader, header *tar.Header) (string, error) { + + outputPath := filepath.Join(outputDir, header.Name) + + if header.Typeflag == tar.TypeDir { + return "", fmt.Errorf("can only untar files but %s is a directory", header.Name) + } + + err = outputFile(outputPath, os.FileMode(header.Mode), tr) + if err != nil { + return "", err + } + return outputPath, nil + } + + if err == nil { + tr := tar.NewReader(gzr) + + loop: + for { + header, err := tr.Next() + switch { + case err == io.EOF: + break loop + case err != nil: + return "", err + case header == nil: + continue + } + return extractAndWriteFile(tr, header) + } + err = fmt.Errorf("file %s does not exist in archive", fileName) + } + + return "", err +} + +func outputFile(outputPath string, mode os.FileMode, r io.Reader) error { + os.MkdirAll(filepath.Dir(outputPath), 0755) + f, err := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + defer f.Close() + + _, err = io.Copy(f, r) + if err != nil { + return err + } + return nil +} + +func doSendGet(url string, token string) ([]byte, error) { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, fmt.Errorf("invalid request: %v", err) + } + if token != "" { + req.Header.Add("Authorization", fmt.Sprintf("token %s", token)) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("request error: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unsuccessful response: %d %s", resp.StatusCode, resp.Status) + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read response body: %v", err) + } + return data, nil +} + +func sendGet(url string) ([]byte, error) { + return doSendGet(url, "") +} + +func sendGetWithAuth(url string, token string) ([]byte, error) { + return doSendGet(url, token) +} + +func latestGithubRelease(repo string) (string, error) { + token := os.Getenv("GITHUB_TOKEN") + url := fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repo) + data, err := sendGetWithAuth(url, token) + if err != nil { + return "", fmt.Errorf("get latest github release data: %v", err) + } + type info struct { + TagName string `json:"tag_name"` + } + var i info + err = json.Unmarshal(data, &i) + if err != nil { + return "", fmt.Errorf("json unmarshal: %v", err) + } + return i.TagName, nil +} + +func latestGithubLinuxAsset(repo string) (string, error) { + token := os.Getenv("GITHUB_TOKEN") + url := fmt.Sprintf("https://api.github.com/repos/%s/releases", repo) + data, err := sendGetWithAuth(url, token) + if err != nil { + return "", fmt.Errorf("get github releases data: %v", err) + } + type AssetInfo struct { + Name string `json:"name"` + } + type Release struct { + Assets []AssetInfo `json:"assets"` + } + type Releases []Release + var releases Releases + err = json.Unmarshal(data, &releases) + if err != nil { + return "", fmt.Errorf("json unmarshal: %v", err) + } + for _, release := range releases { + for _, asset := range release.Assets { + if strings.Contains(asset.Name, "linux") { + return asset.Name, nil + } + } + } + return "", fmt.Errorf("could not find github linux asset") +} diff --git a/build/file_test.go b/build/file_test.go new file mode 100644 index 0000000..0e4a435 --- /dev/null +++ b/build/file_test.go @@ -0,0 +1,65 @@ +package build + +import ( + . "github.com/aandryashin/matchers" + "io/ioutil" + "os" + "testing" +) + +func TestUnzip(t *testing.T) { + data := readFile(t, "testfile.zip") + AssertThat(t, isZipFile(data), Is{true}) + AssertThat(t, isTarGzFile(data), Is{false}) + testUnpack(t, data, "zip-testfile", func(data []byte, filePath string, outputDir string) (string, error) { + return unzip(data, filePath, outputDir) + }, "zip\n") +} + +func TestUntar(t *testing.T) { + data := readFile(t, "testfile.tar.gz") + AssertThat(t, isTarGzFile(data), Is{true}) + AssertThat(t, isZipFile(data), Is{false}) + testUnpack(t, data, "gzip-testfile", func(data []byte, filePath string, outputDir string) (string, error) { + return untar(data, filePath, outputDir) + }, "gzip\n") +} + +func withTmpDir(t *testing.T, prefix string, fn func(*testing.T, string)) { + dir, err := ioutil.TempDir("", prefix) + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + fn(t, dir) + +} + +func testUnpack(t *testing.T, data []byte, fileName string, fn func([]byte, string, string) (string, error), correctContents string) { + + withTmpDir(t, "test-unpack", func(t *testing.T, dir string) { + unpackedFile, err := fn(data, fileName, dir) + if err != nil { + t.Fatal(err) + } + + if !fileExists(unpackedFile) { + t.Fatalf("file %s does not exist\n", unpackedFile) + } + + unpackedFileContents := string(readFile(t, unpackedFile)) + if unpackedFileContents != correctContents { + t.Fatalf("incorrect unpacked file contents; expected: '%s', actual: '%s'\n", correctContents, unpackedFileContents) + } + }) + +} + +func readFile(t *testing.T, fileName string) []byte { + data, err := ioutil.ReadFile(fileName) + if err != nil { + t.Fatal(err) + } + return data +} + diff --git a/build/firefox.go b/build/firefox.go new file mode 100644 index 0000000..b872d8b --- /dev/null +++ b/build/firefox.go @@ -0,0 +1,228 @@ +package build + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +const ( + geckoDriverBinary = "geckodriver" +) + +type Firefox struct { + SelenoidVersion string + SeleniumVersion string + Requirements +} + +func (c *Firefox) Build() error { + + if c.SelenoidVersion == "" && c.SeleniumVersion == "" { + return errors.New("missing Selenoid or Selenium JAR version") + } + + // Build dev image + devDestDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create dev temporary dir: %v", err) + } + + devSrcDir := "firefox/apt" + pkgSrcPath, pkgVersion, err := c.BrowserSource.Prepare() + if err != nil { + return fmt.Errorf("invalid browser source: %v", err) + } + + if pkgSrcPath != "" { + devSrcDir = "firefox/local" + pkgDestDir := filepath.Join(devDestDir, devSrcDir) + err := os.MkdirAll(pkgDestDir, 0755) + if err != nil { + return fmt.Errorf("create %v temporary dir: %v", pkgDestDir, err) + } + pkgDestPath := filepath.Join(pkgDestDir, "firefox.deb") + err = os.Rename(pkgSrcPath, pkgDestPath) + if err != nil { + return fmt.Errorf("move package: %v", err) + } + } + + pkgTagVersion := extractVersion(pkgVersion) + devImageTag := fmt.Sprintf("selenoid/dev_firefox:%s", pkgTagVersion) + devImageRequirements := Requirements{NoCache: c.NoCache, Tags: []string{devImageTag}} + devImage, err := NewImage(devSrcDir, devDestDir, devImageRequirements) + if err != nil { + return fmt.Errorf("init dev image: %v", err) + } + devBuildArgs := []string{fmt.Sprintf("VERSION=%s", pkgVersion)} + devBuildArgs = append(devBuildArgs, c.channelToBuildArgs()...) + devImage.BuildArgs = devBuildArgs + if pkgSrcPath != "" { + devImage.FileServer = true + } + + err = devImage.Build() + if err != nil { + return fmt.Errorf("build dev image: %v", err) + } + + // Build main image + destDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create temporary dir: %v", err) + } + + firefoxMajorVersion, err := strconv.Atoi(majorVersion(pkgTagVersion)) + geckoDriverCompatible := firefoxMajorVersion > 48 + srcDir := "firefox/selenoid" + if !geckoDriverCompatible { + srcDir = "firefox/selenium" + } + + image, err := NewImage(srcDir, destDir, c.Requirements) + if err != nil { + return fmt.Errorf("init dev image: %v", err) + } + image.BuildArgs = append(image.BuildArgs, fmt.Sprintf("VERSION=%s", pkgTagVersion)) + + firefoxMajorMinorVersion := majorMinorVersion(pkgTagVersion) + if geckoDriverCompatible { + driverVersion, err := c.downloadGeckoDriver(image.Dir) + if err != nil { + return fmt.Errorf("failed to download geckodriver: %v", err) + } + labels := []string{fmt.Sprintf("driver=geckodriver:%s", driverVersion)} + + selenoidVersion, err := c.downloadSelenoid(image.Dir) + if err != nil { + return fmt.Errorf("failed to download Selenoid: %v", err) + } + labels = append(labels, fmt.Sprintf("selenoid=%s", selenoidVersion)) + image.Labels = labels + + browsersJsonFile := filepath.Join(image.Dir, "browsers.json") + data, err := ioutil.ReadFile(browsersJsonFile) + if err != nil { + return fmt.Errorf("failed to read browsers.json: %v", err) + } + newContents := strings.Replace(string(data), "@@VERSION@@", firefoxMajorMinorVersion, -1) + err = ioutil.WriteFile(browsersJsonFile, []byte(newContents), 0) + if err != nil { + return fmt.Errorf("failed to update browsers.json: %v", err) + } + } else { + driverVersion, err := c.downloadSeleniumJAR(image.Dir) + if err != nil { + return fmt.Errorf("failed to download Selenium JAR: %v", err) + } + image.Labels = []string{fmt.Sprintf("driver=selenium:%s", driverVersion)} + } + + err = image.Build() + if err != nil { + return fmt.Errorf("build image: %v", err) + } + + err = image.Test(c.TestsDir, "firefox", firefoxMajorMinorVersion) + if err != nil { + return fmt.Errorf("test image: %v", err) + } + + err = image.Push() + if err != nil { + return fmt.Errorf("push image: %v", err) + } + + return nil +} + +func (c *Firefox) channelToBuildArgs() []string { + switch c.BrowserChannel { + case "beta": + return []string{"PPA=ppa:mozillateam/firefox-next"} + case "dev": + return []string{"PACKAGE=firefox-trunk", "PPA=ppa:ubuntu-mozilla-daily/ppa"} + case "esr": + return []string{"PACKAGE=firefox-esr", "PPA=ppa:mozillateam/ppa"} + default: + return []string{} + } +} + +func (c *Firefox) downloadGeckoDriver(dir string) (string, error) { + version := c.DriverVersion + if version == LatestVersion { + v, err := latestGithubRelease("mozilla/geckodriver") + if err != nil { + return "", fmt.Errorf("latest geckodriver version: %v", err) + } + version = strings.TrimPrefix(v, "v") + } + + u := fmt.Sprintf("https://github.com/mozilla/geckodriver/releases/download/v%s/geckodriver-v%s-linux64.tar.gz", version, version) + _, err := downloadDriver(u, geckoDriverBinary, dir) + if err != nil { + return "", fmt.Errorf("download geckodriver: %v", err) + } + return version, nil +} + +func (c *Firefox) downloadSelenoid(dir string) (string, error) { + version := c.SelenoidVersion + if version == LatestVersion { + v, err := latestGithubRelease("aerokube/selenoid") + if err != nil { + return "", fmt.Errorf("latest Selenoid version: %v", err) + } + version = v + } + + u := fmt.Sprintf("https://github.com/aerokube/selenoid/releases/download/%s/selenoid_linux_amd64", version) + data, err := downloadFile(u) + if err != nil { + return "", fmt.Errorf("download Selenoid: %v", err) + } + outputPath := filepath.Join(dir, "selenoid") + err = ioutil.WriteFile(outputPath, data, 0755) + if err != nil { + return "", fmt.Errorf("save Selenoid: %v", err) + } + return version, nil +} + +func (c *Firefox) downloadSeleniumJAR(dir string) (string, error) { + version := c.SeleniumVersion + var u string + switch version { + case "2.15.0", "2.19.0", "2.20.0", "2.21.0", "2.25.0", "2.32.0", "2.35.0", "2.37.0", "2.39.0", "2.40.0", "2.41.0", "2.43.1", "2.44.0", "2.45.0", "2.48.2": + u = fmt.Sprintf("https://repo.jenkins-ci.org/releases/org/seleniumhq/selenium/selenium-server-standalone/%s/selenium-server-standalone-$selenium_version.jar", version) + case "2.47.1": + u = "http://selenium-release.storage.googleapis.com/2.47/selenium-server-standalone-2.47.1.jar" + case "2.53.1": + u = "http://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.1.jar" + case "3.2.0": + u = "http://selenium-release.storage.googleapis.com/3.2/selenium-server-standalone-3.2.0.jar" + case "3.3.1": + u = "http://selenium-release.storage.googleapis.com/3.3/selenium-server-standalone-3.3.1.jar" + case "3.4.0": + u = "https://selenium-release.storage.googleapis.com/3.4/selenium-server-standalone-3.4.0.jar" + default: + return "", fmt.Errorf("unsupported Selenium JAR version: %s", version) + } + data, err := downloadFile(u) + if err != nil { + return "", fmt.Errorf("download Selenium JAR: %v", err) + } + outputPath := filepath.Join(dir, "selenium-server-standalone.jar") + err = ioutil.WriteFile(outputPath, data, 0644) + if err != nil { + return "", fmt.Errorf("save Selenium JAR: %v", err) + } + return version, nil + +} diff --git a/build/opera.go b/build/opera.go new file mode 100644 index 0000000..75ea37d --- /dev/null +++ b/build/opera.go @@ -0,0 +1,128 @@ +package build + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +const ( + operaDriverBinary = "operadriver_linux64/operadriver" +) + +type Opera struct { + Requirements +} + +func (o *Opera) Build() error { + + // Build dev image + devDestDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create dev temporary dir: %v", err) + } + + srcDir := "opera/apt" + pkgSrcPath, pkgVersion, err := o.BrowserSource.Prepare() + if err != nil { + return fmt.Errorf("invalid browser source: %v", err) + } + + if pkgSrcPath != "" { + srcDir = "opera/local" + pkgDestDir := filepath.Join(devDestDir, srcDir) + err := os.MkdirAll(pkgDestDir, 0755) + if err != nil { + return fmt.Errorf("create %v temporary dir: %v", pkgDestDir, err) + } + pkgDestPath := filepath.Join(pkgDestDir, "opera.deb") + err = os.Rename(pkgSrcPath, pkgDestPath) + if err != nil { + return fmt.Errorf("move package: %v", err) + } + } + + pkgTagVersion := extractVersion(pkgVersion) + devImageTag := fmt.Sprintf("selenoid/dev_opera:%s", pkgTagVersion) + devImageRequirements := Requirements{NoCache: o.NoCache, Tags: []string{devImageTag}} + devImage, err := NewImage(srcDir, devDestDir, devImageRequirements) + if err != nil { + return fmt.Errorf("init dev image: %v", err) + } + devBuildArgs := []string{fmt.Sprintf("VERSION=%s", pkgVersion)} + devBuildArgs = append(devBuildArgs, o.channelToBuildArgs()...) + devImage.BuildArgs = devBuildArgs + if pkgSrcPath != "" { + devImage.FileServer = true + } + + err = devImage.Build() + if err != nil { + return fmt.Errorf("build dev image: %v", err) + } + + // Build main image + destDir, err := tmpDir() + if err != nil { + return fmt.Errorf("create temporary dir: %v", err) + } + + image, err := NewImage("opera", destDir, o.Requirements) + if err != nil { + return fmt.Errorf("init image: %v", err) + } + image.BuildArgs = append(image.BuildArgs, fmt.Sprintf("VERSION=%s", pkgTagVersion)) + + driverVersion, err := o.downloadOperaDriver(image.Dir) + if err != nil { + return fmt.Errorf("failed to download operadriver: %v", err) + } + image.Labels = []string{fmt.Sprintf("driver=operadriver:%s", driverVersion)} + + err = image.Build() + if err != nil { + return fmt.Errorf("build image: %v", err) + } + + err = image.Test(o.TestsDir, "opera", pkgTagVersion) + if err != nil { + return fmt.Errorf("test image: %v", err) + } + + err = image.Push() + if err != nil { + return fmt.Errorf("push image: %v", err) + } + + return nil +} + +func (o *Opera) channelToBuildArgs() []string { + switch o.BrowserChannel { + case "beta": + return []string{"PACKAGE=opera-beta"} + case "dev": + return []string{"PACKAGE=opera-developer"} + default: + return []string{} + } +} + +func (o *Opera) downloadOperaDriver(dir string) (string, error) { + version := o.DriverVersion + if version == LatestVersion { + v, err := latestGithubRelease("operasoftware/operachromiumdriver") + if err != nil { + return "", fmt.Errorf("latest Operadriver version: %v", err) + } + version = strings.TrimPrefix(v, "v.") + } + + u := fmt.Sprintf("https://github.com/operasoftware/operachromiumdriver/releases/download/v.%s/operadriver_linux64.zip", version) + _, err := downloadDriver(u, operaDriverBinary, dir) + if err != nil { + return "", fmt.Errorf("download Operadriver: %v", err) + } + return version, nil +} diff --git a/build/testfile.tar.gz b/build/testfile.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3e44f36a371506d080e2930a625f7935a8801e99 GIT binary patch literal 306 zcmV-20nPp&iwFS!I~`d71MSnlPQx$|2Jp;z3QNp|v*TRcArl>n)By=GAh8%?ibb1L zNm>;qo`gr?sTdeZptR-R)(Tbqe#=E?OS$Cqo!WWd+02zk!v{a<)UK*;{Ky5HL`1B$ z2$FZJN()LxLPnC96>|~`Qp8dPV!qKS{xGd-TQ;N2Z0>DmQWUqp-y8HUd&SuLT%1>~ ztbUw-e2Q4s9U&7j^jR8rBaV`oIh00Bn}#CIQEb?7s7PGbe(X}IyD=FfNwz(^-fNZ^ zsz{t2_fG~FhnbtDlA9eXY1Z04FH+5kR+>%wo<%z!`TQ=G;eY>%y|lg5uYBhJv3b6K zeR*o@!4*BzQv5ytlA8R}mgf0l&-35zAISp%000000000000000007usZ-{}!9RMf* E08SK-g8%>k literal 0 HcmV?d00001 diff --git a/build/testfile.zip b/build/testfile.zip new file mode 100644 index 0000000000000000000000000000000000000000..59c526fd1cfa48e750620861b435ee397bcf0b22 GIT binary patch literal 178 zcmWIWW@h1H009=yO + + + + + + + diff --git a/docs/docinfo.html b/docs/docinfo.html new file mode 100644 index 0000000..58665bc --- /dev/null +++ b/docs/docinfo.html @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/docs/features.adoc b/docs/features.adoc new file mode 100644 index 0000000..b6c8ba9 --- /dev/null +++ b/docs/features.adoc @@ -0,0 +1,26 @@ +== Features + +=== Adding Custom Root Certification Authority + +In corporate networks tested environments are often using self-signed https://en.wikipedia.org/wiki/Transport_Layer_Security[TLS] certificates. Such certificates are issued by a https://en.wikipedia.org/wiki/Root_certificate[root certification authority] not known to browsers. When trying to open an HTTPS web-page using a self-signed certificate, your browser by default will refuse to do this saying that "Your connection is not private" or "This connection is untrusted". In Selenium tests you can use a standard capability (`acceptInsecureCerts = true`) to ignore such certificate errors but this will not work when your web-page is using https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HSTS]. + +In order to work properly with self-signed certificates, you have to add your root certification authority certificate to a list of trusted certificates. Our images allow to do this using environment variables. For every root certificate stored in `cert.pem` file: + +. Encode `cert.pem` file contents to https://en.wikipedia.org/wiki/Base64[Base64]: + + CERT_CONTENTS=$(cat cert.pem | base64 -w0) + ++ +In case of MacOS respective command would be: + + CERT_CONTENTS=$(cat cert.pem | base64) + +. Set an environment variable to browser image: + + ROOT_CA_="$CERT_CONTENTS" + ++ +In that case `` will be used as certificate name in the browser certificates storage. For example: + + ROOT_CA_MY_CERT="LS0tL....==" + diff --git a/docs/firefox.adoc b/docs/firefox.adoc new file mode 100644 index 0000000..32fc5c0 --- /dev/null +++ b/docs/firefox.adoc @@ -0,0 +1,119 @@ +== Firefox + +.Firefox Images with Selenium Server +|=== +| Image | VNC Image | Selenium Version | Firefox Version | Client Version + +| selenoid/firefox:3.6 | selenoid/vnc_firefox:3.6 | 2.20.0 | 3.6.16 i386 (dialogs may not work) .7+<.^| +**Java:** 2.53.1 and below +**Python:** not supported +**selenium-webdriver.js:** not supported +| selenoid/firefox:4.0 | selenoid/vnc_firefox:4.0 | 2.20.0 | 4.0.1 i386 +| selenoid/firefox:5.0 | selenoid/vnc_firefox:5.0 | 2.20.0 | 5.0.1 i386 +| selenoid/firefox:6.0 | selenoid/vnc_firefox:6.0 | 2.20.0 | 6.0.2 i386 +| selenoid/firefox:7.0 | selenoid/vnc_firefox:7.0 | 2.20.0 | 7.0.1 i386 +| selenoid/firefox:8.0 | selenoid/vnc_firefox:8.0 | 2.20.0 | 8.0.1 i386 +| selenoid/firefox:9.0 | selenoid/vnc_firefox:9.0 | 2.20.0 | 9.0.1 +| selenoid/firefox:10.0 | selenoid/vnc_firefox:10.0 | 2.32.0 | 10.0.2 .13+<.^| +**Java:** any modern version +**Python:** not supported +**selenium-webdriver.js:** not supported +| selenoid/firefox:11.0 | selenoid/vnc_firefox:11.0 | 2.32.0 | 11.0 +| selenoid/firefox:12.0 | selenoid/vnc_firefox:12.0 | 2.32.0 | 12.0 +| selenoid/firefox:13.0 | selenoid/vnc_firefox:13.0 | 2.32.0 | 13.0 +| selenoid/firefox:14.0 | selenoid/vnc_firefox:14.0 | 2.32.0 | 14.0.1 +| selenoid/firefox:15.0 | selenoid/vnc_firefox:15.0 | 2.32.0 | 15.0.1 +| selenoid/firefox:16.0 | selenoid/vnc_firefox:16.0 | 2.32.0 | 16.0.2 +| selenoid/firefox:17.0 | selenoid/vnc_firefox:17.0 | 2.32.0 | 17.0.1 +| selenoid/firefox:18.0 | selenoid/vnc_firefox:18.0 | 2.32.0 | 18.0.2 +| selenoid/firefox:19.0 | selenoid/vnc_firefox:19.0 | 2.32.0 | 19.0.2 +| selenoid/firefox:20.0 | selenoid/vnc_firefox:20.0 | 2.32.0 | 20.0 +| selenoid/firefox:21.0 | selenoid/vnc_firefox:21.0 | 2.32.0 | 21.0 +| selenoid/firefox:22.0 | selenoid/vnc_firefox:22.0 | 2.32.0 | 22.0 +| selenoid/firefox:23.0 | selenoid/vnc_firefox:23.0 | 2.35.0 | 23.0.1 .25+<.^| Any modern client version +| selenoid/firefox:24.0 | selenoid/vnc_firefox:24.0 | 2.39.0 | 24.0 +| selenoid/firefox:25.0 | selenoid/vnc_firefox:25.0 | 2.39.0 | 25.0.1 +| selenoid/firefox:26.0 | selenoid/vnc_firefox:26.0 | 2.39.0 | 26.0 +| selenoid/firefox:27.0 | selenoid/vnc_firefox:27.0 | 2.40.0 | 27.0.1 +| selenoid/firefox:28.0 | selenoid/vnc_firefox:28.0 | 2.41.0 | 28.0 +| selenoid/firefox:29.0 | selenoid/vnc_firefox:29.0 | 2.43.1 | 29.0.1 +| selenoid/firefox:30.0 | selenoid/vnc_firefox:30.0 | 2.43.1 | 30.0 +| selenoid/firefox:31.0 | selenoid/vnc_firefox:31.0 | 2.44.0 | 31.0 +| selenoid/firefox:32.0 | selenoid/vnc_firefox:32.0 | 2.44.0 | 32.0.3 +| selenoid/firefox:33.0 | selenoid/vnc_firefox:33.0 | 2.44.0 | 33.0.3 +| selenoid/firefox:34.0 | selenoid/vnc_firefox:34.0 | 2.45.0 | 34.0.5 +| selenoid/firefox:35.0 | selenoid/vnc_firefox:35.0 | 2.45.0 | 35.0.1 +| selenoid/firefox:36.0 | selenoid/vnc_firefox:36.0 | 2.45.0 | 36.0.1 +| selenoid/firefox:37.0 | selenoid/vnc_firefox:37.0 | 2.45.0 | 37.0.2 +| selenoid/firefox:38.0 | selenoid/vnc_firefox:38.0 | 2.45.0 | 38.0.5 +| selenoid/firefox:39.0 | selenoid/vnc_firefox:39.0 | 2.45.0 | 39.0.3 +| selenoid/firefox:40.0 | selenoid/vnc_firefox:40.0 | 2.45.0 | 40.0.3 +| selenoid/firefox:41.0 | selenoid/vnc_firefox:41.0 | 2.45.0 | 41.0.2 +| selenoid/firefox:42.0 | selenoid/vnc_firefox:42.0 | 2.47.1 | 42.0 +| selenoid/firefox:43.0 | selenoid/vnc_firefox:43.0 | 2.53.1 | 43.0.4 +| selenoid/firefox:44.0 | selenoid/vnc_firefox:44.0 | 2.53.1 | 44.0.2 +| selenoid/firefox:45.0 | selenoid/vnc_firefox:45.0 | 2.53.1 | 45.0.2 +| selenoid/firefox:46.0 | selenoid/vnc_firefox:46.0 | 2.53.1 | 46.0.1 +| selenoid/firefox:47.0 | selenoid/vnc_firefox:47.0 | 2.53.1 | 47.0.1 +|=== + +WARNING: Firefox 53.0+ images require Selenium client 3.4.0 or newer for Java and Node.js and 3.5.0 or newer for Python. + +.Firefox Images with Selenoid +|=== +| Image | VNC Image | Selenoid Version | Geckodriver Version | Firefox Version + +| selenoid/firefox:48.0 | selenoid/vnc_firefox:48.0 | 1.10.0 | 0.13.0 | 48.0.2 (page load timeout, native events and proxies don't work) +| selenoid/firefox:49.0 | selenoid/vnc_firefox:49.0 | 1.10.0 | 0.13.0 | 49.0.2 (page load timeout, native events and switching between windows don't work) +| selenoid/firefox:50.0 | selenoid/vnc_firefox:50.0 | 1.10.0 | 0.13.0 | 50.0.2 (page load timeout, native events, switching windows and proxies don't work) +| selenoid/firefox:51.0 | selenoid/vnc_firefox:51.0 | 1.10.0 | 0.14.0 | 51.0.1 (page load timeout, native events, switching windows and proxies don't work) +| selenoid/firefox:52.0 | selenoid/vnc_firefox:52.0 | 1.10.0 | 0.15.0 | 52.0.2 (page load timeout, native events, switching windows and proxies don't work) +| selenoid/firefox:53.0 | selenoid/vnc_firefox:53.0 | 1.10.0 | 0.16.0 | 53.0.2 (switching windows may not work) +| selenoid/firefox:54.0 | selenoid/vnc_firefox:54.0 | 1.10.0 | 0.17.0 | 54.0.1 (switching windows may not work) +| selenoid/firefox:55.0 | selenoid/vnc_firefox:55.0 | 1.10.0 | 0.18.0 | 55.0.1 (switching windows may not work) +| selenoid/firefox:56.0 | selenoid/vnc_firefox:56.0 | 1.10.0 | 0.19.1 | 56.0.1 +| selenoid/firefox:57.0 | selenoid/vnc_firefox:57.0 | 1.10.0 | 0.19.1 | 57.0 +| selenoid/firefox:58.0 | selenoid/vnc_firefox:58.0 | 1.10.0 | 0.20.1 | 58.0 +| selenoid/firefox:59.0 | selenoid/vnc_firefox:59.0 | 1.10.0 | 0.20.1 | 59.0.1 +| selenoid/firefox:60.0 | selenoid/vnc_firefox:60.0 | 1.10.0 | 0.21.0 | 60.0.2 +| selenoid/firefox:61.0 | selenoid/vnc_firefox:61.0 | 1.10.0 | 0.21.0 | 61.0 +| selenoid/firefox:62.0 | selenoid/vnc_firefox:62.0 | 1.10.0 | 0.22.0 | 62.0 +| selenoid/firefox:63.0 | selenoid/vnc_firefox:63.0 | 1.8.1 | 0.23.0 | 63.0 +| selenoid/firefox:64.0 | selenoid/vnc_firefox:64.0 | 1.8.4 | 0.23.0 | 64.0 +| selenoid/firefox:65.0 | selenoid/vnc_firefox:65.0 | 1.9.0 | 0.24.0 | 65.0 +| selenoid/firefox:66.0 | selenoid/vnc_firefox:66.0 | 1.9.1 | 0.24.0 | 66.0.1 +| selenoid/firefox:67.0 | selenoid/vnc_firefox:67.0 | 1.9.1 | 0.24.0 | 67.0 +| selenoid/firefox:68.0 | selenoid/vnc_firefox:68.0 | 1.9.2 | 0.24.0 | 68.0 +| selenoid/firefox:69.0 | selenoid/vnc_firefox:69.0 | 1.9.2 | 0.24.0 | 69.0 +| selenoid/firefox:70.0 | selenoid/vnc_firefox:70.0 | 1.9.2 | 0.26.0 | 70.0 +| selenoid/firefox:71.0 | selenoid/vnc_firefox:71.0 | 1.9.3 | 0.26.0 | 71.0 +| selenoid/firefox:72.0 | selenoid/vnc_firefox:72.0 | 1.9.3 | 0.26.0 | 72.0 +| selenoid/firefox:73.0 | selenoid/vnc_firefox:73.0 | 1.10.0 | 0.26.0 | 73.0 +| selenoid/firefox:74.0 | selenoid/vnc_firefox:74.0 | 1.10.0 | 0.26.0 | 74.0.1 +| selenoid/firefox:75.0 | selenoid/vnc_firefox:75.0 | 1.10.0 | 0.26.0 | 75.0 +| selenoid/firefox:76.0 | selenoid/vnc_firefox:76.0 | 1.10.0 | 0.26.0 | 76.0 +| selenoid/firefox:77.0 | selenoid/vnc_firefox:77.0 | 1.10.0 | 0.26.0 | 77.0.1 +| selenoid/firefox:78.0 | selenoid/vnc_firefox:78.0 | 1.10.0 | 0.26.0 | 78.0.1 +| selenoid/firefox:79.0 | selenoid/vnc_firefox:79.0 | 1.10.0 | 0.27.0 | 79.0 +| selenoid/firefox:80.0 | selenoid/vnc_firefox:80.0 | 1.10.0 | 0.27.0 | 80.0 +| selenoid/firefox:81.0 | selenoid/vnc_firefox:81.0 | 1.10.0 | 0.27.0 | 81.0 +| selenoid/firefox:82.0 | selenoid/vnc_firefox:82.0 | 1.10.0 | 0.27.0 | 82.0 +| selenoid/firefox:83.0 | selenoid/vnc_firefox:83.0 | 1.10.0 | 0.28.0 | 83.0 +| selenoid/firefox:84.0 | selenoid/vnc_firefox:84.0 | 1.10.0 | 0.28.0 | 84.0 +| selenoid/firefox:85.0 | selenoid/vnc_firefox:85.0 | 1.10.1 | 0.29.0 | 85.0.1 +| selenoid/firefox:86.0 | selenoid/vnc_firefox:86.0 | 1.10.1 | 0.29.0 | 86.0 +| selenoid/firefox:87.0 | selenoid/vnc_firefox:87.0 | 1.10.1 | 0.29.0 | 87.0 +| selenoid/firefox:88.0 | selenoid/vnc_firefox:88.0 | 1.10.3 | 0.29.1 | 88.0 +| selenoid/firefox:89.0 | selenoid/vnc_firefox:89.0 | 1.10.3 | 0.29.1 | 89.0 +| selenoid/firefox:90.0 | selenoid/vnc_firefox:90.0 | 1.10.3 | 0.29.1 | 90.0 +| selenoid/firefox:91.0 | selenoid/vnc_firefox:91.0 | 1.10.3 | 0.29.1 | 91.0 +| selenoid/firefox:92.0 | selenoid/vnc_firefox:92.0 | 1.10.5 | 0.29.1 | 92.0 +| selenoid/firefox:93.0 | selenoid/vnc_firefox:93.0 | 1.10.5 | 0.29.1 | 93.0 +| selenoid/firefox:94.0 | selenoid/vnc_firefox:94.0 | 1.10.5 | 0.29.1 | 94.0 +| selenoid/firefox:95.0 | selenoid/vnc_firefox:95.0 | 1.10.7 | 0.29.1 | 95.0 +| selenoid/firefox:96.0 | selenoid/vnc_firefox:96.0 | 1.10.7 | 0.29.1 | 96.0 +| selenoid/firefox:97.0 | selenoid/vnc_firefox:97.0 | 1.10.7 | 0.29.1 | 97.0 +| selenoid/firefox:98.0 | selenoid/vnc_firefox:98.0 | 1.10.7 | 0.29.1 | 98.0 +| selenoid/firefox:99.0 | selenoid/vnc_firefox:99.0 | 1.10.7 | 0.29.1 | 99.0 +| selenoid/firefox:100.0 | selenoid/vnc_firefox:100.0 | 1.10.7 | 0.29.1 | 100.0 +|=== diff --git a/docs/img/favicon.png b/docs/img/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7667a253de682519c97b22e058c6fd2306b6bf76 GIT binary patch literal 1908 zcmV-)2aEWLP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ] || [ -n "$STOP" ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done +if [ -n "$STOP" ]; then exit 0; fi + +if [ "$ENABLE_VNC" != "true" ] && [ "$ENABLE_VIDEO" != "true" ]; then + EMULATOR_ARGS="$EMULATOR_ARGS -no-window" +fi +ANDROID_AVD_HOME=/root/.android/avd DISPLAY="$DISPLAY" /opt/android-sdk-linux/emulator/emulator ${EMULATOR_ARGS} -writable-system -no-boot-anim -no-audio -no-jni -avd @AVD_NAME@ -sdcard /sdcard.img -skin "$SKIN" -skindir /opt/android-sdk-linux/platforms/@PLATFORM@/skins/ -gpu swiftshader_indirect -ranchu -qemu -enable-kvm & +EMULATOR_PID=$! + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /tmp/x11vnc.log & + X11VNC_PID=$! +fi + +while [ "$(adb shell getprop sys.boot_completed | tr -d '\r')" != "1" ] && [ -z "$STOP" ] ; do sleep 1; done +if [ -n "$STOP" ]; then exit 0; fi + +DEFAULT_CAPABILITIES='"androidNaturalOrientation": true, "deviceName": "android", "platformName": "Android", "noReset": true, "udid":"'$EMULATOR'"' +if [ -n "@CHROME_MOBILE@" ]; then + while ip addr | grep inet | grep -q tentative > /dev/null; do sleep 0.1; done + DEFAULT_CAPABILITIES=$DEFAULT_CAPABILITIES', "chromedriverPort": '$CHROMEDRIVER_PORT + /usr/bin/devtools --android & + DEVTOOLS_PID=$! +fi + +if [ -x "/usr/bin/chromedriver" ]; then + DEFAULT_CAPABILITIES=$DEFAULT_CAPABILITIES',"chromedriverExecutable": "/usr/bin/chromedriver"' +fi + +/opt/node_modules/.bin/appium -a 0.0.0.0 -p "$PORT" -bp "$BOOTSTRAP_PORT" --log-timestamp --log-no-colors --command-timeout 90 --no-reset ${APPIUM_ARGS} --default-capabilities "{$DEFAULT_CAPABILITIES}" & +APPIUM_PID=$! + +wait diff --git a/selenium/android/fluxbox/aerokube b/selenium/android/fluxbox/aerokube new file mode 100644 index 0000000..b990e81 --- /dev/null +++ b/selenium/android/fluxbox/aerokube @@ -0,0 +1,175 @@ +############################################################################### +# +# name: aerokube (based on ubuntu_light) +# made: paultag +# date: 16-10-2010 +# http://pault.ag/ +# +############################################################## BACKGROUND ###### + +# background: flat +# background.color: #2c001e +# background.colorTo: #2c001e + +background: fullscreen +background.pixmap: /usr/share/images/fluxbox/aerokube.png + +############################################################## FONTS ########## + + +menu.frame.font: Ubuntu-10:bold +menu.title.font: Ubuntu-12:bold +toolbar.clock.font: Ubuntu-10:bold +toolbar.workspace.font: Ubuntu-12:bold +toolbar.iconbar.focused.font: Ubuntu-10:bold +toolbar.iconbar.unfocused.font: Ubuntu-10 +window.font: Ubuntu-10 + +############################################################## MENU ########### + +menu.bevelWidth: 1 + +#menu.itemHeight: 35 +#menu.titleHeight: 21 +menu.borderColor: #525252 +menu.borderWidth: 1 + +menu.bullet: Triangle +menu.bullet.position: Right +menu.frame.underlineColor: #ffffff + +menu.title: flat gradient rectangle +menu.title.justify: center +menu.title.color: #FFFFFF +menu.title.colorTo: #FFFFFF +menu.title.textColor: #333333 + +menu.frame: flat gradient crossdiagonal +menu.frame.justify: left +menu.frame.color: #FFFFFF +menu.frame.colorTo: #FFFFFF +menu.frame.textColor: #333333 +menu.frame.disableColor: #aea79f + +menu.hilite: flat gradient rectangle +menu.hilite.color: #aea79f +menu.hilite.colorTo: #aea79f +menu.hilite.textColor: #000000 + +############################################################## TOOLBAR ######## + +toolbar.bevelWidth: 0 + +toolbar.borderWidth: 1 +toolbar.borderColor: #aea79f + +toolbar.height: 20 + +toolbar.justify: center + +toolbar: flat gradient rectangle +toolbar.pixmap: +toolbar.color: #aea79f +toolbar.colorTo: #aea79f + +toolbar.clock: parentrelative +toolbar.clock.justify: center +toolbar.clock.color: # +toolbar.clock.colorTo: # +toolbar.clock.textColor: #333333 + +toolbar.workspace: parentrelative +toolbar.workspace.justify: Center +toolbar.workspace.color: # +toolbar.workspace.colorTo: # +toolbar.workspace.textColor: #333333 + +toolbar.button: parentrelative +toolbar.button.color: #333333 +toolbar.button.colorTo: #333333 +toolbar.button.picColor: #333333 +toolbar.button.pressed: parentrelative +toolbar.button.pressed.color: #aea79f +toolbar.button.pressed.colorTo: #aea79f +toolbar.button.pressed.picColor: #000000 + +toolbar.iconbar.borderWidth: 1 +toolbar.iconbar.borderColor: #333333 + +toolbar.iconbar.empty: parentrelative +toolbar.iconbar.empty.color: # +toolbar.iconbar.empty.colorTo: # + +toolbar.iconbar.focused.borderWidth: 1 +toolbar.iconbar.focused.borderColor: #333333 +toolbar.iconbar.focused: flat gradient rectangle +toolbar.iconbar.focused.color: #FFFFFF +toolbar.iconbar.focused.colorTo: #FFFFFF +toolbar.iconbar.focused.textColor: #333333 +toolbar.iconbar.focused.justify: center + +toolbar.iconbar.unfocused.borderWidth: 1 +toolbar.iconbar.unfocused.borderColor: #525252 +toolbar.iconbar.unfocused: flat gradient rectangle +toolbar.iconbar.unfocused.color: #aea79f +toolbar.iconbar.unfocused.colorTo: #aea79f +toolbar.iconbar.unfocused.textColor: #444444 +toolbar.iconbar.unfocused.justify: center + +############################################################## WINDOW ######### + +window.roundCorners: TopRight TopLeft +window.bevelWidth: 4 +window.shade: false +window.borderWidth: 1 +window.borderColor: #333333 + +window.justify: Center +window.title.height: 21 + +window.title.focus: flat gradient rectangle +window.title.focus.color: #000000 +window.title.focus.colorTo: #333333 +window.title.unfocus: flat gradient rectangle +window.title.unfocus.color: #111111 +window.title.unfocus.colorTo: #444444 + +window.label.focus: parentrelative +window.label.focus.color: # +window.label.focus.colorTo: # +window.label.focus.textColor: #FFFFFF +window.label.unfocus: parentrelative +window.label.unfocus.color: # +window.label.unfocus.colorTo: # +window.label.unfocus.textColor: #aea79f + +window.button.focus: parentrelative +window.button.focus.color: # +window.button.focus.colorTo: # +window.button.focus.picColor: #FFFFFF +window.button.unfocus: parentrelative +window.button.unfocus.Color: # +window.button.unfocus.ColorTo: # +window.button.unfocus.picColor: #888888 +window.button.pressed: parentrelative +window.button.pressed.color: # +window.button.pressed.colorTo: # +window.button.pressed.picColor: #000000 + +window.handle.focus: flat +window.handle.focus.color: #1f1f1f +window.handle.focus.colorTo: #1f1f1f +window.handle.unfocus: lat +window.handle.unfocus.color: #1f1f1f +window.handle.unfocus.colorTo: #1f1f1f +window.handleWidth: 2 + +window.grip.focus: flat +window.grip.focus.color: #525252 +window.grip.focus.colorTo: #525252 +window.grip.unfocus: flat +window.grip.unfocus.color: #1f1f1f +window.grip.unfocus.colorTo: #1f1f1f + +############################################################################### +# EOF \ No newline at end of file diff --git a/selenium/android/fluxbox/aerokube.png b/selenium/android/fluxbox/aerokube.png new file mode 100644 index 0000000000000000000000000000000000000000..91f4b6947ec0ec3b4875a2a920e5f96f3f5d2cf5 GIT binary patch literal 127633 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%0DCjWDZJ8rEmR+ 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 LmL->f@F literal 0 HcmV?d00001 diff --git a/selenium/android/fluxbox/init b/selenium/android/fluxbox/init new file mode 100644 index 0000000..b41a387 --- /dev/null +++ b/selenium/android/fluxbox/init @@ -0,0 +1,7 @@ +session.menuFile: ~/.fluxbox/menu +session.keyFile: ~/.fluxbox/keys +session.styleFile: /usr/share/fluxbox/styles/aerokube +session.configVersion: 13 +session.screen0.strftimeFormat: %d %b, %a %02k:%M:%S +session.screen0.toolbar.visible: false +session.screen0.toolbar.tools: \ No newline at end of file diff --git a/selenium/automate_android.sh b/selenium/automate_android.sh new file mode 100755 index 0000000..2ad3944 --- /dev/null +++ b/selenium/automate_android.sh @@ -0,0 +1,251 @@ +#!/bin/bash + +set -e + +die(){ + echo "$1" + return 1 +} + +require_command(){ + if [ -z "$(command -v $1)" ]; then + die "$1 command required for this script to run" + fi +} + +request_answer(){ + prompt=$1 + default_value=$2 + if [ -n "$default_value" ]; then + prompt="$prompt [$default_value]" + fi + read -r -p "$prompt " value + if [ -z "$value" ] && [ -n "$default_value" ]; then + value="$default_value" + fi + echo "$value" +} + +validate_android_version(){ + version="$1" + type=${2:-"default"} + abi=${3:-"x86"} + avd_name="android$version-1" + build_tools="build-tools;29.0.2" + replace_img="y" + case "$version" in + 4.4) + platform="android-19" + emulator_image="system-images;android-19;$type;$abi" + ;; + 5.0) + platform="android-21" + emulator_image="system-images;android-21;$type;$abi" + ;; + 5.1) + platform="android-22" + emulator_image="system-images;android-22;$type;$abi" + ;; + 6.0) + platform="android-23" + emulator_image="system-images;android-23;$type;$abi" + ;; + 7.0) + platform="android-24" + emulator_image="system-images;android-24;$type;$abi" + ;; + 7.1) + platform="android-25" + emulator_image="system-images;android-25;$type;$abi" + ;; + 8.0) + platform="android-26" + emulator_image="system-images;android-26;$type;$abi" + ;; + 8.1) + platform="android-27" + emulator_image="system-images;android-27;$type;$abi" + ;; + 9.0) + platform="android-28" + emulator_image="system-images;android-28;$type;$abi" + replace_img="" + ;; + 10.0) + platform="android-29" + emulator_image="system-images;android-29;$type;$abi" + replace_img="" + ;; + 11.0) + platform="android-30" + emulator_image="system-images;android-30;$type;$abi" + replace_img="" + ;; + 12.0) + platform="android-31" + emulator_image="system-images;android-31;$type;$abi" + replace_img="" + ;; + *) + echo "Unsupported Android version" + false + ;; + esac +} + +validate_android_image_type(){ + type="$1" + case "$type" in + "default" | "google_apis" | "google_apis_playstore" | "android-wear" | "android-tv" ) + ;; + *) + echo "Unsupported Android image type" + false + ;; + esac +} + +validate_android_abi(){ + abi="$1" + case "$abi" in + "armeabi-v7a" | "arm64-v8a" | "x86" | "x86_64" ) + ;; + *) + echo "Unsupported Application Binary Interface" + false + ;; + esac +} + +download_chromedriver() { + pushd "$TMP_DIR" + wget -O chromedriver.zip http://chromedriver.storage.googleapis.com/$1/chromedriver_linux64.zip + unzip chromedriver.zip + rm chromedriver.zip + popd +} + +test_image(){ + tests_dir=../../selenoid-container-tests/ + if [ -d "$tests_dir" ]; then + echo "Running test suite on image." + docker rm -f selenium || true + docker run -d --privileged --name selenium -p 4445:4444 $1 + echo "Waiting for image to start..." + sleep 20 + pushd "$tests_dir" + mvn clean test -Dgrid.connection.url="http://localhost:4445/wd/hub" -Dgrid.browser.name=chrome || true + popd + docker rm -f selenium || true + else + echo "Skipping tests as $tests_dir does not exist." + fi +} + +require_command "docker" +require_command "sed" +require_command "true" +require_command "false" +require_command "wget" +require_command "unzip" +require_command "cut" + +TMP_DIR="android/tmp" +rm -Rf ./"$TMP_DIR" || true +mkdir -p "$TMP_DIR" +cp android/entrypoint.sh "$TMP_DIR/entrypoint.sh" +cp -r ../static/chrome/devtools "$TMP_DIR/devtools" + +appium_version=$(request_answer "Specify Appium version:" "1.18.1") + +until [ "$?" -ne 0 ]; do + android_image_type=$(request_answer "Specify Android image type (possible values: \"default\", \"google_apis\", \"google_apis_playstore\", \"android-tv\", \"android-wear\"):" "default") + if validate_android_image_type "$android_image_type"; then + break + fi +done +until [ "$?" -ne 0 ]; do + android_abi=$(request_answer "Specify Application Binary Interface (possible values: \"armeabi-v7a\", \"arm64-v8a\", \"x86\", \"x86_64\"):" "x86") + if validate_android_abi "$android_abi"; then + break + fi +done +until [ "$?" -ne 0 ]; do + android_version=$(request_answer "Specify Android version:" "8.1") + if validate_android_version "$android_version" "$android_image_type" "$android_abi"; then + break + fi +done +IFS=';' read -ra emulator_image_info <<< "$emulator_image" +emulator_image_type=${emulator_image_info[2]} +sed -i.bak "s|@AVD_NAME@|$avd_name|g" "$TMP_DIR/entrypoint.sh" +sed -i.bak "s|@PLATFORM@|$platform|g" "$TMP_DIR/entrypoint.sh" + +android_device=$(request_answer "Specify device preset name if needed (e.g. \"Nexus 4\"):") +sdcard_size=$(request_answer "Specify SD card size, Mb:" 500) +userdata_size=$(request_answer "Specify userdata.img size, Mb:" 500) + +image_name="android" +default_tag="$android_version" +chrome_mobile=$(request_answer "Are you building a Chrome Mobile image (for mobile web testing):" "n") +if [ "y" == "$chrome_mobile" ]; then + sed -i.bak 's|@CHROME_MOBILE@|yes|g' "$TMP_DIR/entrypoint.sh" + image_name="chrome-mobile" +else + sed -i.bak 's|@CHROME_MOBILE@||g' "$TMP_DIR/entrypoint.sh" +fi + +chromedriver_version=$(request_answer "Specify Chromedriver version if needed (required for Chrome Mobile):") +if [ -n "$chromedriver_version" ]; then + chrome_major_version="$(cut -d'.' -f1 <<<${chromedriver_version})" + chrome_minor_version="$(cut -d'.' -f2 <<<${chromedriver_version})" + if [ -n "$chrome_major_version" ] && [ -n "$chrome_minor_version" ]; then + default_tag="$chrome_major_version.$chrome_minor_version" + fi +fi + +tag=$(request_answer "Specify image tag:" "selenoid/$image_name:$default_tag") +need_quickboot=$(request_answer "Add Android quick boot snapshot?" "y") + +if [ -n "$chromedriver_version" ]; then + download_chromedriver "$chromedriver_version" +fi + +rm -Rf *.bak || true +set -x + +tmp_tag="$tag"_tmp +docker build -t "$tmp_tag" \ + --build-arg APPIUM_VERSION="$appium_version" \ + --build-arg ANDROID_DEVICE="$android_device" \ + --build-arg REPLACE_IMG="$replace_img" \ + --build-arg AVD_NAME="$avd_name" \ + --build-arg BUILD_TOOLS="$build_tools" \ + --build-arg PLATFORM="$platform" \ + --build-arg EMULATOR_IMAGE="$emulator_image" \ + --build-arg EMULATOR_IMAGE_TYPE="$emulator_image_type" \ + --build-arg ANDROID_ABI="$android_abi" \ + --build-arg SDCARD_SIZE="$sdcard_size" \ + --build-arg USERDATA_SIZE="$userdata_size" android + +if [ "$need_quickboot" == "y" ]; then + id=$(docker run -e CHROME_MOBILE="$chrome_mobile" -d --privileged "$tmp_tag") + sleep 60 + docker exec "$id" "/usr/bin/emulator-snapshot.sh" + sleep 30 # Wait for snapshot to save + docker commit "$id" "$tag" + docker rm -f "$id" || true +else + docker tag "$tmp_tag" "$tag" +fi +docker rmi -f "$tmp_tag" || true +set +x + +if [ "y" == "$chrome_mobile" ]; then + test_image "$tag" +fi + +read -r -p "Push?" yn +if [ "$yn" == "y" ]; then + docker push "$tag" +fi diff --git a/selenium/barrier/main.go b/selenium/barrier/main.go new file mode 100644 index 0000000..14aa58c --- /dev/null +++ b/selenium/barrier/main.go @@ -0,0 +1,121 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "net/http" + "net/http/httputil" + "net/url" + "os" + "os/signal" + "strings" + "syscall" + "time" +) + +var ( + listen string + gracePeriod time.Duration + target string + queue = make(chan struct{}, 1) +) + +func init() { + flag.StringVar(&listen, "listen", ":4444", "host and port to listen to") + flag.DurationVar(&gracePeriod, "grace-period", 300*time.Second, "graceful shutdown period") + flag.StringVar(&target, "target", "http://localhost:4723", "target proxy url") + flag.Parse() +} + +func signalContext() (context.Context, context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + defer cancel() + stop := make(chan os.Signal) + signal.Notify(stop, os.Interrupt, syscall.SIGTERM) + <-stop + }() + return ctx, cancel +} + +func main() { + ctx, cancel := signalContext() + defer cancel() + err := mainCtx(ctx) + if err != nil { + log.Fatal(err) + } +} + +func mux(ctx context.Context, u *url.URL) http.Handler { + mux := http.NewServeMux() + mux.HandleFunc("/wd/hub/session", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + select { + case <-r.Context().Done(): + return + case <-ctx.Done(): + http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable) + return + case queue <- struct{}{}: + } + (&httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.URL.Scheme, r.URL.Host = u.Scheme, u.Host + }, + ModifyResponse: func(resp *http.Response) error { + if resp.StatusCode != http.StatusOK { + <-queue + } + return nil + }, + ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { + <-queue + log.Printf("proxy to %s: %v", u.String(), err) + http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) + + }, + }).ServeHTTP(w, r) + })) + mux.HandleFunc("/wd/hub/session/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + (&httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.URL.Scheme, r.URL.Host = u.Scheme, u.Host + }, + }).ServeHTTP(w, r) + fragments := strings.Split(r.URL.Path, "/") + if r.Method == http.MethodDelete && len(fragments) == 5 { + <-queue + } + })) + return mux +} + +func mainCtx(ctx context.Context) error { + target, err := url.Parse(target) + if err != nil { + return fmt.Errorf("parse target url: %v", err) + } + server := &http.Server{ + Addr: listen, + Handler: mux(ctx, target), + } + e := make(chan error) + go func() { + e <- server.ListenAndServe() + }() + select { + case err := <-e: + return err + case <-ctx.Done(): + } + log.Printf("starting graceful shutdown in %v]", gracePeriod) + shCtx, cancel := context.WithTimeout(context.Background(), gracePeriod) + defer cancel() + if err := server.Shutdown(shCtx); err != nil { + return fmt.Errorf("graceful shutdown: %v", err) + } + log.Printf("stopped") + return nil +} diff --git a/selenium/base/Dockerfile b/selenium/base/Dockerfile new file mode 100644 index 0000000..dd1cede --- /dev/null +++ b/selenium/base/Dockerfile @@ -0,0 +1,79 @@ +FROM golang:1.17 as go + +COPY xseld /xseld + +COPY fileserver /fileserver + +RUN \ + apt-get update && \ + apt-get install -y upx-ucl libx11-dev && \ + cd /xseld && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /xseld/xseld && \ + cd /fileserver && \ + go test -race && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /fileserver/fileserver + +FROM ubuntu:20.04 + +RUN \ + apt update && \ + apt remove -y libcurl4 && \ + apt install -y apt-transport-https ca-certificates tzdata locales libcurl4 curl gnupg && \ + DEBIAN_FRONTEND=noninteractive apt -y upgrade && \ + echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections && \ + echo 'UTC' | tee /etc/timezone && \ + dpkg-reconfigure -f noninteractive tzdata && \ + echo "gtk-cursor-blink=0" > /root/.gtkrc-2.0 && \ + apt update && \ + apt install -y ttf-mscorefonts-installer \ + ttf-dejavu-core \ + fontconfig \ + fontconfig-config \ + fonts-dejavu-core \ + fonts-liberation \ + fonts-ubuntu-font-family-console \ + fonts-wqy-zenhei \ + fonts-thai-tlwg-ttf \ + fonts-ipafont-mincho \ + fonts-sahadeva \ + fonts-noto-unhinted \ + fonts-noto-color-emoji \ + libfontconfig1 \ + libfontenc1 \ + libfreetype6 \ + libxfont2 \ + libxft2 \ + libnss3-tools \ + xfonts-base \ + xfonts-encodings \ + xfonts-utils \ + flashplugin-installer \ + xvfb \ + pulseaudio \ + fluxbox \ + x11vnc \ + feh \ + wmctrl \ + libnss-wrapper \ + xsel && \ + mkdir -p /var/lib/locales/supported.d/ && grep UTF-8 /usr/share/i18n/SUPPORTED > /var/lib/locales/supported.d/all && \ + locale-gen && update-locale && \ + fc-cache -f -v && \ + adduser --system --home /home/selenium --uid 4096 \ + --ingroup root --disabled-password --shell /bin/bash selenium && \ + mkdir -p /home/selenium/Downloads && \ + mkdir -p /home/selenium/.fluxbox && \ + chgrp -R 0 /home/selenium && \ + chmod -R g=u /home/selenium && \ + ln -sf /bin/true /usr/bin/xdg-open && \ + apt-get clean && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* + +COPY fluxbox /usr/share/fluxbox/styles/ +COPY --chown=selenium:root fluxbox /home/selenium/.fluxbox/ +COPY aerokube.png /usr/share/images/fluxbox/ + +COPY --from=go /fileserver/fileserver /usr/bin/ +COPY --from=go /xseld/xseld /usr/bin/ diff --git a/selenium/base/aerokube.png b/selenium/base/aerokube.png new file mode 100644 index 0000000000000000000000000000000000000000..91f4b6947ec0ec3b4875a2a920e5f96f3f5d2cf5 GIT binary patch literal 127633 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%0DCjWDZJ8rEmR+ z`7+#HN$J(JN5-()q-z9s&N`^Vrr!Gmkfn0!WVf=yhXQO$zQ?K^NwLx`zv|AU)+VMi zO(s(@_TBkF1+7Fqn4}`P4;umJcL-#xat?C%h^89ehiE>2_eEOgLfrKV7lxJpm~+;x zd{o_-Yyu06JpAHMV86>-+$ANNI;WHD-c!58t7@7~0pJ?l3o87<*n%Nb9d zrX6B{9Mumo+=tBHa(bv%x9j(1`Oj9<>3H2OmXeOsrk-sHx7_>88~PPw@sYxd_Rt99 z5+T%ZFxy=0wQm58tFbiEKxLPuB)V#sBvK0MA!gVo?v(Yfo)WXys#`I)*_=N2jOPRM z%G~okD#iuc4Y07xGNr61k|*L6IC5mw)Vj-Q@3%2H9_lD8;ACV zd!wM7&1U{R{nMCBcXz|&i1|SGMiK7oIB5*+nug&;ScB=o>VQfs ztZH&R1$4@9II*^KYFp6Lbg&%dh=|P#Kfwf|^$UZ~4_QdXY~RYYl#2R@?3?TE-`_9v zm%lS+)(gLdiHb=v(S9RbMV zKzW9c(uTz{1`eos;UHoHEB9;`D5+Hfm=|RQ!jGr@m&TF0HJpD84#$bUdQxB zaQxx7)M+Y2I*D3wNrX8{V{C&uZ609JbDaSfRAQ9qhU}bh-6$+9j*8jID`=W|)89v3 zti2nYRP>`*M{-H9-MIC<(=MQ=Ms`4A5(B4d)}t;qlH)&A-YV;6RIUdG;Rz{NPK~JI zax%LfmORgo(anJ#%FDh?#ZZjr?EFVE9nZ*_wwE?C36fX_E#K_%km7GthL8&;0UHfa zTC2efNuIgSkL=sYoI1{z=%rlG(W$Q2Is~rCR6p*A!^4E#Sd5ys&&xB%ELFR$&F$hk zfF7_Z(%^9>3cN}aVW_pQz?9D9g7(PjeXXfZZd%4+R%9e0 zEQ@KM&lu&(cd%g7q6*`A4t|R)#b1|(FZYBSA75{X9^eUKnlm0)Z-gnH7L(Cw+to@` zP4>ov0$A_VUQM^ZK>K(Y9h)>I?z~TVL7J0hr%#mrf-Igj_q5LXS}@gGqSlc!w-fKvGaJw(q_48+=HYo41);umtP?4iOahaH&&-}>0O03p(Y}6%A2Aj=t6~R~vRCYBe!X;l_!jn2i~#obpSTD1uQSF zN>twbmjnbk;^5Y-N2K!GVh2f~eW&McyTXqpz{EyV5eKShFe=i5V$*zQL1*OwRjX}l zLAx3ee0D(Xqg|@uR2|?{J^s<#ImYL{c6GjE?0p+J9lA2i=bvY91O=xZM;+`cD!79U z#l)~~P}72ezji$APTQI!AZq+y$tQqi{a=VH{O7BvF98P0W0s)zc+)xG(L2Gv+Jv=lVZ2mr_aKfL(g_^tnQL;f4T^?z>VfB&KXmxlcJ zANr;tSlVnP7MB9|@8p!0Dy*%o+4AVqjv18?NT8vin#Amk31fZ|IkpisyQ4}&xNe>7 zdzaV@h+NL^3?K!(!81jSh!yS#JOf9RkZ0b@}_`IpT! znj=N>+uJPhad8FG?(Pjh2k~$~ocwTIE*`T){YgA=)#P;Qi@wgz0hDe8a5+SQ>X?+I zWGN$I|G)Wwl>>^EU#a{w)8;v@V1!n5&}pyq#%BXMc=X-K8%tGXv|}9=wg8A~IH_#5 zIlihtIrrPZ#RNpG<`5zbKIm7LX&`Bto?`#Hb9tRH(UFn4&ZTkS%PWs!1$0gt<)gY! zf|shPOxjAid&h14%?wP+1M)&2%L^}LjP5#`+$y(#`a!EyA&^X9Jw)aB_TGoK+QA*` zrq{hW{LSKhkv*}jl|XI}21Go_Jlg9CL~7Ad1MBsfUWJzxuGSl<9;u?DvJN6Dqu?+! zmYF^B#_s>m+WlYqBX)C6ZttY zTYGxW;lJ6r7H(r>Ow`TqqGZ}%u5z?p;qjHE)oxhFs-8vcfkoi-bG#Em=t*H*BU~fZ zYDW1N?7769C&z10zAEFRkSfA~%F0SQTG|1W$ADBFnes3qsBmF{r)y|T%$4}r11xtG zYMkg$kPJBM&V{{$JR0nqrT063zB1Feq%LWcsp&!y6}N!N!MaOy_pfd#7C`w6jY`*7 z8?znG9^1;zsubaDR324KL|~Vx1sfwqnGlQ08)-cu$JRmG8j_wD(pHG*Ki2@Ua~DXL zC{n0iBtC8O5V_i!Rm{+nti$Eb$g#nRZ>jN-(L!+U*PHAQj<4TaV`O9;eI0L}CU~_M zs?u+_vAkdp6|GSJz?$*w#>R*gsBIOX`jw`~4%(ZfQm$K=le22w^mEPhu)~P(g^^r7 z1%*x@=v{7?K<%Rn#f)G2EEcS@N(*U0q~mv~J1S>Fq&6(}NO9Hp2UHZyJuDvQF{rNA zRS{k+lVLt~hY^jJew>;iY7;qsIlYXyZXpm{1vY;NvS*IJU>Pglv*~X65r2(?nrPDf zcp9RnWDdV_iC;wyWAM&&ry*`WH7(XuvGV*yITL9dk?f!w*VhC;mbX?zSTOmG7}qNwvNp z8)C6#T1izkyJu)jtX7Cod&#inXI}?Kw&CZt`?JC6MRwf9*XhpMDSxZ1o?ssE;znHz zJF2F0A^Q9|0!^EWrO~IgokVJPKtxlUXmHEler0LNG(DJO5U6pQ;VppCUD)Q!h@XFo zY7!-l9by8kc&o!J2}L`({AmVpqtpbT`gvR-*fml=9PDsq7Oqg>XxI3{m;RfYZv}e> zF9S!$WLzw~En13yHC&shpX~jsfZKY~nxe37!jnBM%tmKvZ_H#Gl7n_X8%_t(w&|L0 zmVz0R7X_^1xd#;mkd^rw{_<~@YhOA1VRAsi&hu<2nayEcdBgSGu#hGN9Sr4zurWGdNzJ<$hD*1C~Hu^fgiYQmTNdAx2RD1RNcVq!8M^Ha|&Zn48 z-QTuBDM3^FybJKiYL}ulXg;HwAXIM}Taaalqy@S$m{m-X{1ns(iYK@zjT(~Y0yQh4!UOifKq%9T4ucLbi$2R5T-Yg zNLOd0;MzEG%*=~y>*O}2s2Q6Uorx)maqlF+eIJy3-ZJ`LFTeXuQVfGe+vLr1n-6p8 zi{~yV&P3zr?+(OrGZRc0VA0Ea+wYOJZ<*wfl+4XGaFOU|%oKAy6hmlP5PF!wwj&W& zK8Pjl328mma2%JcbWvPn^B3oxmYPA{&%8LbPZwfLJVisd+y>G1=L8bQF-q!9==sKoghnTH~}hU}n@2 zt;A5qdjCQnwUc@|pWSC2OSAB_wEWGaQIbmBH2!vB(|H5B+)3a#!OQ-{*WP+B6e-|V zgwf<_LDcrrN@RbtR1AF!ru@5Fjo`ewGLMt7RB&3;jhd=ki%tD0^(;MHDvLe8oZo+L zL`aXQ+-L{p(|iai6V=Ps{*FCHl2oUS+8mhW$>YOnmo#Th>iWM6un2JWEJc%w3B$_U zExQ0KTstWZvoIyB9B;$c3+H~5)v_XQJe_2d5Ka_d&qT`m%>+Lt3k?h9blE`Bs*>wl zr;6_}B{ISHhDT2F8AR?YEyh)+zP%oI+4^l#ke!8i_faRYUQRRb2f+@Fvd*)~2J1y2TqL*(18X*~jSe zZF|F>x&hJX7Ot)x4vn4do12d3(#Q9p&XRv=WwCjoub<65sAd(}btv{gi}CuFvD9*A4Hu%3GMmn2lShhoTV* z$J{onqR+9cu)HCS)}{1aRizW+unGT_&&Y>Sq{Y$b1_LbR7RrVG_0%qU5S+?j41c3B z*eaa03-HMzp{0dh4l=W10PWZ=3w&nEj63H?;=2)@KX=7Sq=^*SoLV?)Xm7+i^*9r1 zWF6bN_+%*8`K@Iwn%_7>@rYLr6x?(sB~7P#VLib9EH95g6QKN4_c34JDZ-!4G`!)a?ufHV6KQlf_ zw7pENK&f|#@vqsb4*)YYQ}1HI+urT@b%kGMd?-k7r20=_8~u46LG31^c>N*n^@+~N zv{T%xMjn`Cw!DZI%$tTI>$DZWJf^sXMiX!e1n&eXnEIcHs-pNF)>iz*euH&KPG`9n|3QDa4Dh0 zd$H5xlKc1ZJA}T=lS58As7@|Ql<9b43zz9ictGM$tsK{?>aQJExwl%q;bk>WqkMu0 z-8A!!Ey`eZ!BJj%fA;dy@JAU=jxWBq7N2temKV{unY-1D#KCD6Amg{?tk10Azddd! z*B=%XSZ7i{#pyO?=pKh8&=L6xUvK;bK9-VK{mDKR|H=yVf&@_@3yPEV`Cl5`7Dj0!Opv$m(gy3&apmy2g|V; zCN-@yvzZesrcmdz=RhVJp`=>;7$CZ@fUE z--U-@aH(H_euO(_OFjjACb+M_`!u=x`pg1(br!p5Va^aDlX^ztTT7>yS$Y|<+!wrbvNTbPn+=uZ)bmtX=DJ3BZct}3dTkF*bjVqF^_G9x8`Dmrl)G;4 zmrOxwTi4TZzUDt*Yg#L#w8GfsJJ@Y7-B~GX)k7~r!Dib ztF^d|lr>V-C=>a$eDvdYM4Y?^W<7ouGHh#e61b>Gv$WgjJJwLPC%DEU+w zHCi>gsF__nUE0AK0r69C+p#ZGyt2>OtkDmC)t|*a0|$EWCEVDNHJYIc!yJt^F(^ks zS3mPrV-{j&ybtsxG6^s`R$1?qY#7GEVeL>Hyk|sz=Z){1v!PFzcMIPAY1`br zX=o!@-qV&=buY~co913%S|<>;zlMvYDjxF<)!N_3p;y$P!*oM>9{Pc)^wP7FNl__# zW?_PEM9?MIVNH#>cIhpgr*~!n;E^`XT4lsREF8G1p`sSUs>Ko_mGABfL^$=~;l^A{ z0i$UC)?>Ro06F3@owWF8vyH;21JTzv_@w( zW%5J*K1*O;ijE_!P5l>poygJVgVCy_#MdM-k0zo#N8?QiJGz(L=dey^JcoHo9^kSe z5#<87wmX5*-no| zbhNa{f^YmczfU;|XyPI=uqzvq^+otO{;76jYn%-y2|g_$u9|eOeU5XFYsYqEFQ4kT z=Kkio)jk?1Gu=f+eO| zcf7xD0Jm%X(c)P>qDaPhEKs&WO`N zzZs~cyMJ{h5JG}-Ux;w&6tCjf$*=tD$(wYQ1>K*dn9cOk45rPbd;)b@&n}R7r;VD$ zg)dkGz$H&OQrGQ)w#z}`ii$22s){cr6M$}KXlYUAHoVcHG>(^4v6V#>cLai%ne_M@ z6;RM%QT6EE0Po$3R*3X_FgdtOUjPr_#-fIOdo=>&mSQH<3#FjAZr6x)ORo1n^Oj&` z2336;me8Z}IN3y!y3VaIdVaa_m?nDhpC?g$i-C@HyUW~j>J%A{nAQe+W8vy(w^oz5 zD`rWF9vpy3rnit#ZZ2uiEtE^Qr+QGqbU)bjZS@5wh)Xn@dG?Sh@~+J0x$GuH?XYGU zcWom(8V0tdrqA8R?Qjh?EKidp-YZx&ybEknYN5E6@1SuMk(ohsCh^=oAuP}=D0@WR zwm$cXrK@q#B0VR$BYryG{WJ_F8Q5r1mwKT}f~khSp?nWMS#li>LVc*EiyzxS2$=Xn zB5UV0f_(XtGsyXl$kOFs^+RXB?B3K!hbpDBy{b;j!=4HFaaAyxv<5U9gnN{amUgO& zgNSkqQES`=J#zGqJO_i-5iUO#$X zG!@pxcdlMDI#HdR+@J+q*731PVN3#`ItM>}1<|Q5{M1eSw4Zu-Emw?C?J8c102B@J zOLH3wGL0P+j%~VDi&zDIvs?Te!g>1ayo4XEr4-H4k$dD7$ajCN&z#uf~=< z!p=wlXBj*~pHMb))K&jCYUWsi+ST?MOW~0Bt%=)ers(FzRrhcFOa5|f=ZT6COu338 zx6CGD?SqD{zG-D7yZxngPmk(09zYgjdA}F;IA6FKYF#y!r9C*+PRNX-X54n2DcNJ) zi7D=`OIA|H)_&73uu@s5&ii4UH85z|&T&f^`}a_La3sIt`kd~In~j%rO%ts+=mtVw z`8s{oQ-12*#k0S6Lc$0u@7`Z&(ugr}FQk);FVK}y&wj_17uSAms>!G_5zKL{ro58&t3BZcz!@{1 z-H)o@Sj*#v-(qLDtXUv?^?;orHapyhuS;M_o65>zb$9%QCgb=fKE|!pZeyuF349WC z)Oj%V1ubnS-6vJ|>8?~>{*vB^yv_I(+6m?2^=l2etEI%zdOU1p_m+=k(;f-7OdhI0 zke%}4NY{=MxTfdYJ0*m85l3D`UzS5H&IL#+Uq2@0wxz_og^Hlh2X`-(xq3}*b+tyb zl@uy5VF*2UeAwldAA?;B@52deYW5jCAhISHm#fJmO5zSEf4aUqb7$u z2_E8foe$z61w0c!IYjXnJ)QEMHO4E!&lCRHuN~fBZU5K0D=L~{EXX3tWpG+is?CgF z2L6+aNI)(1FXv9)d>lWePP=-#PgEuyf2~lb??R+|3xU{z%R|pwIGp6)Bwnj{%|NTI zU;f8#^QGoOrlY!AwcIj~0n(yH-F3bfSgQStT{!_0)=hNrSJEXoum`6>aVXNgFVMEI zvXk!d9!JgSxC&r6bJs@dl--YKYY8`HGVelct>YA(xS&tlr^EiRiunf}Gj38ddkN40 zxb;7_Qucrmi5yAC!me*)IT$*PS?lW9bc1SD$U697WF#ll)L)B!Wi>Y-QO=xG;Nx_u zgGukZsn;+Q`@iYN!^|sKzU%abl6keBCppb{hk4c3lYbmk!@&(D3P&U48ZEi!ZAFWT za`FR??K#_iO&#ZRtclO0f{SO<+c?RUM_IP7Nyb{xr=qUAD+G}JVjm*2f-npjEl=82)uCpqg7Jjj_U<~}5Y3^g zHQUCSfIpgyhDnDNZ`}^_`1G?r88$i5-S^3>IcEdcxH&CporP#dRH>EkfAYo16L7lA z&T!IG3$^*lQMwWvojYY0JjQ9!eN|LxxIao4$F7HV*G<>tZY=f|2Kol!qko>M5n(WL zM{Gw==hkXZf)Uf=9ykaN%o4p8@c4RZfqif33?eaAU7{7UXRl z#gM@2#wiZ-=jX`^UNPqC2EAoUq!+J?)lh}rfe%JGwZHR?xkytm}WcP&6}TM zD4f{{^0~?#Zs^}Qe#cdB-q>~3m^8e&g=F>bWrXi#c({*XVQG-sSP=`&~$TY#+6U9K1o5rzE5s z-|HAcz~4qz^x@MbY3bu77d4oXV=jXP##x+fF%zBV+72DBM*^uSxK(6cWL*5XvDz*u zuBaX!O<%F90ZC}`O$$Cu#NF~*2l2Q=Iqj^3^5igZ!H+5&v2LQDn0IAWi?JkKcj?kq z%S*F=p&HaPEV%NDH()fJF1lh`{%vwKno70mcfx1tgPLgZ8+q6oM&;NyjtNs|CmG!6 zR-k7%tYsQr3usT#ao~JTw}UO` zSCtJ#ysG% zz^;Y*3H?VfB@r+-9{|8#Z>TDpI(VugXYJIg>-^K0j(3A#ns~7FQIvakJ$s#>wT@0Q zy=1JXr&R3nF9oOMthTWoldVkCNqBG$a^kW;vK-0iu2Iw(e_VSXu@b71s&MDL$xQ}Q zj{mJT_JUrsQZutXH~_DSV>{X93RY(LxC;ba_H14$_-@b_aul77c?38@{c^X2$)ujM zL&nEEUezd_HS}t>F7VF$R-0ZpLi-UU8RPJxkUf&(0gO!d-!8{y)bpe_p0l{{x#opZ z=&?hPh8(x2=erT7gcK7I2kF?{1NVM~iI=LacDcnt3zlV!02NdK1zS)1o3a+PK6yYA z>U<%0j1%3G`8@fm$2|E>FB6sd>Qn}F#iegW(N#NC8+kB3Y-mx z6$Zm~1meoYlCQqlxTwty`huGLCoWB%{R!H2{^l)D>-vCX%0mDjk4nkj(tP|13v2=WZj`}a>V3)3@HR=VJr4Cdjq^xLI@oa$ueKNw5(pmpFx8 zG~x?}4nuMdI{2tUV@m^8rY8!L_7}-QD;c#&(pt3bNtpw6?8G#1byJR6k~l+*{$<6y zr!6_x$yVYt5EKs~85d5cf*w-ra+(h{+7V2xjutf+;4W9_!eDK=>6NrBq$}D}VM1V~ zD~Z#L{jPpIaHduE((&?6&(Dwy7kzQ0`3+g3v-yimPo>7)m<*GyKJPhSvXF9Lfr&WwK@>&Ar8Nu!Q^J#(+d>4{25=Yx+nW)WAXB*Q0d)1$2u z=!Y4dvC;XPfwR%+&O|XE%f_P)i;JU(@bj*=n{ww4>v;L?)n=~wDR!u7yLil^`FO7x z&{-3@O|ZnrIE+b5bTKh^tMQX<10ORC0>_#;2?SX{5Mk#|LwcKhgRgo94C+4 zjAsc1FH&SUr-ykOZr@DUK3v_H?h(rs20cPPv4Ms4%Wv~QV?2*%g#eroi&ApzyULG7 zfh@TZci`*RXngg7{RxxfZAVrjQ?p33?#1g1(Gfm3@8RKI*P1qblN^L{W_B-gyK{Gx zLXLU*6UXlnQit9(eO6bOhPX_p!ci-hS=QMO9_c_ErEfyM$b4Z(Xa6hd@_R0r^83m$ z@;AUjtBtKE*DG^`ifN^IaBwM6Ew0g6&QTV{;^nGo`sy~9 zf=WrPvY{s#y|GHFZSjS~QJT%A&Y3F=0ciSPB|}f2O>b z5c*k4MMb38zl9>q^-zU!l@qs@sMnDc(o4nLeS8?d?kGu~p3_&iOH^ZIZtSL4v{nhT z0J01!GYn0?a9e@ds&gYgjlP&VtP%Z`S8dLj@6TG}{0T@YYa$Jf&TQVwxl6=mPZj@- zvC5ebn64|>d6q{DS(98?>fpeglb&J0T`|3sKNVB9TdqYiT>U(2EMI&O5$V$EeE`77kkxbVggEnj`9xf;Q(h0kG(ME9e&=$NhvNQ%3kS&C$j8kA2@=Z{!!%d z`Jv4$tIm0u^CsQk?&Voc9upAPJdwl~-$o!Z7l z`Y=JdJctX%vDo{UIQ(1Vb-0rstVYSxWLR^V%P`-$S%&Rt-d^V3+jswdQDBQs;%j}g zSL?xSv`lxs9Uhf5$!l$HEBi;{lt2ZFY1S)P6$2zChF!$gtz~?Hg!&r|samAfNzvHK z-UO+vA%J$@1~;w1=UlpKsPj2m}nF(r&$K5c^# zTV~2@LHZ?W@`X-0dm{$Ru=E1u4~~m7Hx+JUmwf7v|3h_js`t1_Mn-0oXX9oL*l3}P z6Xt5ahR>b!Efs%~ZsH6m*7PMY<4GWnL+RgJUD0~L?^wu!*=}D>&=E#fFHyaP3CsBFVHCkiOjbWi&l(TZ=9Zt@UllbK> zNtHE8)-QAq>x+XZSjESQo9M^>#KJ0SHq~1dW$I#!dyk-2oO-ubS-2vCoE@Jf(_f8Z zI0qLN;-h-DB<}Fzc{97&FhbfR+;07GV)rYm%a3wP*B|>wd9jEubqNi9VcQo&9-gWA zhP`K_B+tn%&KMw?wRSQ4&JDAT^gAr+i(O=y^^?R$Yotai)rWfgePQ3?W@>dtoRX?P zHFJ>AH>=i$niKws-^mVAB9CZB4KReYkP0nD!< z*%}dPceyg!Gt^+@getRFHrMRI;8kptIF!?T1(Hy7Q)*3RobN*_J{Tt27bgrM!uj?8 z5-{4UGv*=KILacFyu2+%wn#X(8M$B`xDa{3KF ztH`;0$jDPxqBj~-x%Wfz=Fx%F^`(GP0S9IMVd zzN`aSyIerypU;qcR6fq;es+LgC0ajHYNtxpva!&&-Kh+e8Nf8n>uLg9kArDD&!5SZ zT5(38^7bqWez{V1Y}>Z_atuHAv~;{)hMISH_#CSd??$c#)W+MdG&<`NCgh&ISLA$ThpzSjKC_CC9jpdo zgs8bjTQzBMh*lL18NF{ZTCypRRX5dDyZp$I!v$h@bY=!c+GX=_rDbIb<}d!Bq$;iq zD`Rq1lImPdo;WTi1_~oriZs6uT{4YmRuYI8wc+ts@Io;rXg|iyeE^yd1os}0c^@n=ljD91j=o><>w9U<8iSQmR73QB&}8*#(c6o&(MA^ z%zVU+XukTOr_uUOx0|pW_dbD-Z|6Z=kKr|77+st9$~IacC<}up!s`a=0UrMlpjvbfeFcQhm7R_|k$s5_zHmXd z!LaDeP0yY%*o2Xog$4N(v4KkCh!{&Uds^i&iO@=l1C)XX`n?=wG^wcVwr}{xFZ4zP zyWsLZREcNB%;P=w4%wjs%kHk|MTO)3|xzN`a`s;~&Dff9Ja9I2hl2#yrTy=-c9&s!2=xWQ2Z`>*%no z>Rz*lvc|-vg_XQ&J9Z?nV0}{)5qviGvhM=(Odew;c*}ZFNMD~K_@7ZzP*hZG$KWDW zWc#%{_OXs)$GXeNDtS9?KEYa-$|iy}pnUlsPC)BLhA%#ehu&lk8UWsCh41cE0giJi zgl6GWv~2jleN4oX9`K1xy%%A_x_Lfh%c{wBbS!9fz-wA%rBO{Z@eCm__tfT|>jCsr zLKs*9R7zm1$IeTOkr>Zgg#*mVWPvYQIL~+wQqh7j3WSC~y7|RnKlJe+`L`Q7lAtUet9h6?iufNWFZ2HI~&FQS3xmr1l0rM@eE_ZTV>V!|yEy zV|%pU#6~;Cvpd=Uz@j}6G%ap9{5|Lbl=Y+igzeBTo>`zBl%iRxYmnXSzD1%$&?D*1 zDLL8G&$+2VTj;B|?Cw;k-@bYBd+2jif`fNV9_gAArxXJ)`9`A(D(>Di*Xg5Gr2?iu6*f7%CA{TNm{YC3XmO?R zlgW2EAY!-rwf97oS$1FowYT=h8~^|IR&8|u3|%h_=jyk{-j3XpxPK*bw%};fsz12( zgNu_ZX3EUR-^Ts(nwE;qC9T3X4kzXChi32M_!->A zE)?EFbNwb*+cJ`uM>lc%<}oN@x~cqI2B4_OdHU+d`Sdxub^FdgFD9n%v&flceDosf zeEL7wd#kW0qpxioL6i_sDM3O7L`oC{gdtQ!x|<;-B!})42?Yu1?uMaj=n(0S0fwPF z2Bd4?{|x^A2j6wQ2k-kHd`I7NIM+4L?Ad$mweD5-8ecGHe3&kKb0-9)q@>CT<|o{k zA1RFqu93D!OyO8o@SEbLaqf2x-MLYlFJ8I(^gkVfw%r=nZ3rnZ1{|us57ef$E$XPG$I;?&F=$qZU%eFSX)d+`Y0 zI>Vz;yVz%VE*;#I`P4_ZT#mMs+wSHl?%|7xiD5V@RCIKp%~wajK?QTHJzxhH0aK*x zjLBbIB*-s!8OF_(O1Na^jNrXX_01WD9o%5{znmZt80dzI0(vzZ7Jo4RiP``DiM;5g z>Xcq5tJ!ZxV;uwHkb&&7hk)|Qkkql}Wp4W{tDNTUz*vAoU<5_? z+QCMYvfS|H*#Q)R?)6dxcw6i!f2vIwUq>@|vxh`~$G83+6#xd_rBftDG9+t>oflZHnZyUpO5yFC*NoASnk zw33EQ_uZW?03jS%w9c;L%{1`Q<%)gJCBnzzbE7-%FFVyA0dp+!0TykbHA~ylwDPHj zX2!_Ur{3sax!Z-p5t%O7z?!7Ia)^9{U%^%R2>-ELfK{u)1Kf5 zCI)DT)43WQ44DF&4;UoP{K#2Csr5*&`*p&Rap0ZAzk`tN4)Fv+eM~NiQCvV4=kPw4 z6lc_CA=vsHXauUly-^E_0N1pIY2_4yWeUSgxkrSrS9CJ3Y$(9+qb}$4gVu3;`;aoqgy4ZcRa`~04E)bEAx0IwaM(+SgLECVnCB}u?1*cvE=NB_} zLJy-js40}sv4kpC!glX72&aa9y3xGtzxdy{&3T@T&${nIf#}gt0{=AG(S?f8mi|T# zgNhCEi``G1z&}BOw61~DyazP%6vL~8J}E1q8AO;Z$C{qpak47wpl|~^HZV*No4|>O zagaYGDA@k#Xnc^>UC|2Zxoqx?=W%;Qs2>Y*qI=~tdtf9*980$9ag&wyaq6R602l=1 zt((qrP|ep~LRY6t6K8FTdfys=0c%b2dMX2RKw_a?=Y`*0whi)S*?H4z#iFwe|i!K&gYcBY0-a)uYHRRrx z2|t?$Qxsm=>&lc;UYYYmZyZ75+G=VPJGdD9SZc?yhKFHYnAn#D25l7jwx%iK1ummE z9bHKz)Q<6;U$`c=8?McyUq|Y;{w8)u4~ywZ`yUb*J~B5Chc?L!2M$KD#&#~IkLvV& zbB>RXzvrn4$13(G1Sq0YxhAg3th(aKimX&UPTY9y+N1SM|D`nF&ASwG(-hz^- z`nd{wHc@ySHLEe3UK+3^(vGSVvdM(HKwBQr)U4yW5}hFETFxVdi@73L7BfH}F4W$y zx2MNpOi>)rd#x}0+6!up#J4WTmL(svTx^nr>`uMkQFk;hEAUbFc^wrm)G({H@lE_^ zFX_Z>H6(e1$yboqr3+@*02LM0#QU3a0IYin!0hb)cy4jb6oHrZ+vSt|fV-Kn3V2HB z$Y{qs)%|VPI@rX+ka7ACUej2jrSl;Yj@jktx9Y<+yT3e$khA?XZI%>uz&L5>rx0qU z`eeytEFYm4Sl_u#N`Ar|B3#daUVF#Y_%GGOA;qqz>`QjlN;Ui+sF%C2>e6qF z$XaD161zR`58_&@RBvVn2|E<1s6I@DY3sPV^z(E9ZT0pRx?h0-0B$Zf-hV)h*=UZY zXeLn6o)al2APE%0OhBxc>Phl!QQxFqrlf6eHAM)Ty-_PEPXXI8Nw%)0%#|u)-Mu7h z`Cj46N0V5(84dm{ni#T$C#$rF)PX5I3vQ*ajNR#RiWi)?_j z>x~+pWiccFwwym0g69uFn|cmjAD-ur!e?Rf=Zm=c>3>*V7?M$+ zKYTJCD55`yY;qZ>X4WCrM@B}9=w=By8-}zZzT+3(yl_ZTPA)XXb(N|Ri`U%`;4+0G z8uc2V@9K?2tGrR;hkF@p>wFp2P@9nc9QSsj;SY5;&4BiP=9q#tat!IGim<9l4t=|b zM@~VZ1^?Ihr3(<=jz-E0n?dO>;mud7KpkC`6Aax;iJ?7!5q7d%Bn$?ihfEWJ-0(48 zesM&|9dvtAX+ibJVHk;&UW2(diIY3u!J)ro6c}0?)=`AH`k=Fd#23ma9CVb zO)ZC1Ua-u{)M4WTVCz8Ee&r?T564Aq3yG(np?L7-&tJUao&%?OG=FaSQnPX#PRwUL=PSwQ?`%)Gk1PnASlvrXedjjZ*|FVaV$@T;M0xMCuvuIqySe;5BWp#= zky>x{GP77}y@a{t_Ax|KQW6+XQWfwY%90sAJNY~r(VzpeZdj4ko-mG?en=V)zw9nD%fNOX6pCpLG2X-@;4iI|C8 z;7Il1c0!Dj@G$_0v@l(6>aQM+sjBN_1EdAuVN;b~0Rquz$0Ey=H!HfQ1=`9r5)G8Q zg<+}^WA8-e-!fhRZC|d7+L?P+QJ1oS?o7(s1Zr~C3=E!B~j?#6tOy;2-Dx+ zAE=R7>*}UBzU0I-FQ0lJqi~v_o2cv46Z6TKlL5x3wVrc(1P~#wy}VVS--_+rRQg$w2aU4inG+FJFu`DM%Lprhqb$5x1v*jlE=)1fQALjF9$w)tpS0pfze5PD#4m8?36RKfO z_6Y$0&O`92;5yF9^&TS}H8U9i?Ean1U>T@YxwxH-OdnoZyA+dyg6ak_@plL!i=**@Gp1pxV`szS(VVPlPIpYH?AFO*=lch4_>${%2?gFRt-vBse z4Z{u07|tWJQf`-Rj)8#W#O6Rc{vxSN##4JLy@^|bS&;M|qtYC$d zXNWWy3F;*Ca0vDFZu}HYDfsj{${Li<5AqFJaTY$e+fPp21d*1a`#~e8EDdQ}WGvX%#)pM<>k-zg+PG&QF?=ZiJCz`ZcC7+HFs4~!YRuJzw)sR!U>};5ALyO>{5K{ zC36W54n~#&6hte>drGAQSnmMHb`Rgg^e~D=`LK_Ba2-%&POuRlIkuC7aLu zrASiqTTTYv@XhLnjdGiFo3(Q5P`+Vb?Eoj+L>8@TO@;ME#l&&mQ`7whZ@7Anp?hjV zg_{rnml<>11`qsBX5Fp%@Vo)$9D%dtNb(;aXVQm5PLeYJxDP6~&IT5qM!EBLHGt

Llnr6CxmQnn(Ns2^Nn=$t#}newjxZS#>o<%-w#kPB%1T_Tx=DR|byl#I z7!-}JazoHr{l9m6;t>MUrX03{02$aCO7eJ5xtjHxY-KQe-h)*>P4>429XO}m_hP;*qA-WIuyU3^2RIz z^u}#CLrh>b&X9~a5cy>0xL;iBJW_kb+TBNLz+Gm4?f4pJPhbIVA&ebpiUmwLE&X)9 zoOM+$4QlzP2VVKegzW)1B_A`n9%%fIiQ&{k9cu*4x@x7T z-i`t}5k~8w6QaOF-rjGR<#ofWh8$J-AiHOg9e74%Gbw2tm`f?Yy2ejen_FaBpOz>sgNTK4A7o zgUH!to@j#;30!1J22@5x)n8a2ny}WRgw{yezwF?Ya@Kg_In*0z2h~XOpG{4@DEof+ z`)DMPQvxarA#ojSK`54PCfN@t0>cS_af>e8xBgw3J0_k}7^O)2&=ZjALI57~h`apl z1a?~xmlvs-9V^U$8w7uL>tr3D=hj>5{!lDS);D|{ku}E_OmuZa_zfIAD$wb^DW3MY zFZ~JGf0sHd0NsVrDlPh7R-wWG7Zqw~ePcAYzV}6Z_@k?39)EAOj2Xqpg&rv1D#A9} zhdFoO))}Pei?^_hjs&jIeBCN+;>p7yR z6?_o_YJRKSS^(gFXZ#o3fw8`-ST}N@0Ua4paz4v4eY2?+as{YqWG{oX@WhCoT92MC zw7gI^vc}wFdiRX&59@4g#+I+xu9Pw{3PH~&^k<;^;%v(dw~*^-FQLVKTvgp{f4Ljw zp^J61T7Bs9^7493Ga3r!nC^RkqM_Dl{=gQBn8a_$R1v;#bnWS^jRj}&#R|I@ZV|_D zYE_7gQACZGY9BX#k&^922D?!d?YlKX=8=H?m@(+bC^d}fde_WtF`tk={MSXh`Lu(x z(x^K^<$f`^U`0GEx+F_UmCy6p?j*;EcbS=_c~v@!Ayd}hglWZfsYFWH^BbubA}T)+ ze$R{!81Y%$c&r6%DHq@t+~~Efzc>SHqX79puFcybz*UvSFt540Hsq^Gd+R=DE9p#V z9+udg`;$F_%#~^tsL_v3{N_Hxhg*nsg9ySM`|Lg_=gN%(@u@-}{4EVM!iT!UkQ7qQ z2GWfVe<4)6?f1-h?VW)rA+)XSLro{}yBIayC1pZ~YH&Ru3+}*BNY(mRSb`3EnoX`y zVY8g7i za_~g~9BlHU{|*Dg|AG;A-~nEOc`%9`c!2wac`zyxcrdF09t^$#9*oQZ&wu&h|KM%^ zji2~0-}YaA_}^LZf4=yC{)_+l+y1jB_cpLD7lS#cflCNH`dxPc9y!eOpWXRizxRK= zt^fU#`!Cn_Uw-(1e_Q|G-^U2i|3F6n$M^RCJm~+mxMIGjpEgy!bCoFboc!LMm4maW z)Kt#i@|j-H74AO`QqDU@4Y;+yjO1SuAAfv&w!=&BdH74$ZG*`Zh?JOHS*e1-i4D3X zz`#)zz=i=Mqa_1r?7q7_;o#eKK(#O7rWpRjJ1On~&rOifE^qcVYrM(aU%FN*LSe9}*xwTnYA2EZPA4dcS z1qoOiV%xrd|JD5&<3AIsU-f?MwzfUjLRC)Ar$NDkpR?ZAo;5}S1y*T z)(MfrV`EtuJQpT(tTAmRNEe2%u#|g#TR!29q+;B^`?0);#%%l;q z?3x)E=Y{)G;;i9l@Jy?A^+rzOCg8%_w3p*|nZ!AYOFVysbEBh;B=dM=BzEE~EPO3a z5Dh>Q$PFNl6Ih#0pc@Od0nMjRyfPS#UArUiIw~U7sJgU*_$TCye7Y>u? zsvP##kbAFbG9i3*2ALixKckCov$7zM0QuTJ2gb{e0&|kLuPl8_@VlPl$tS&4#27Td z^%?Okg*BCy4mF0rlEUxZ$Zct8Yqh(z)gY|;U~Lc%>^U@BI<^j;s9@1%b@EwR2*^Um zwZs|{D4rR)j(&r70+XnI>ntOTKr2>d^@5qa_7E^58>f1V$l#@24ru$5rF58rz;vZE z>8C(z4OG>s^wVGCRF>n}gCKSnt?nFh9X`7cb|bD=-5O&=qZXs69IO6rm26(oWc`;?v6ghTB0ZLhb+N-9n6s1X zh~5vK`TzrYsrw5d7$=^C7H_ZEDEt-MWj()=4gwtSzvQVPE2_v0xfh}0@UyBdVal_9 zzBvc^_z!mC3cRXNAUXJj)@A-HWDuBTZgbsF_8q_b#vJP__)p8&Tj{y3kOSNUCkC~v zC!p1-;u=_Wj5t>>-r40q7;HamTBeC3NdaUgfA+`v7oBi&i`mLD=-TOUwpcoE=Y+X@ zpXtiSJ%V(=zTgkbm%!be=_&k1C$I#UXaVVte|?fkD4$1Wm+u<6_lagltjCyepTJA8 z4`_;rdi5$Vz}Y~i&(n(4)dlL1e(zVXP%bU3tQ;fi&Z*;hN_AuLEW^VQWkq4}78V6h zn*nA+Er9X}6j*t|C9=9k#1Ef{1V5Qu7FyvuuwdSKDgWNq&8CknDmpfmpeEVC{6#>) zaeAjPa|`8aU2AQ9(l65JijLWlYn=pw?i}Y@C=&-(=T^*%tGQURi%lId%7Iwg;38!S z)Masl!74VZ*g{T#X&XsCxNsap8HzCk(~#-%(4 z<9%m+Z{QPtWXkU+{j|B^)rO%~oy|D(mdWoT6PZg${n&dGZHui!@nMNF8?WKKulz)J zumX(MvKlfD!v)*$yTPcbzx@Fb!{Lu3NQrvMuJ@Q~?(!dZZ{;MymO_|759G!c0o~3e=2kK8n4Ap2Y$Q@+qkh8QN!$BAK21jAMh5l2-$A4Z#Qb^PSfeQf zudbD9V!7yUKBMc2uQfC;wt{>;U|HTZF6Q`Z;^}YX+OQwzvz;WEow=M^nv8u{Ub;D- zGy)0hvU)nzUzJ}l0W`+evP_Oo=hagA(h{8TKl(z@P20X9+xn85p!KK3dcI+86@JT7 zXBZp^L6%t6Age1Ps;JBxM=F>AeF)&2aL@E=K)!$!w-jLot*E^05YH`_#@h&py_Hak zwrkR>L~gId_iy18g+zal{7Li16qTaY#-~I1(unG{1c_dD;2>Xv;LqZq70s;2mk9NN6GT%Gs!9UX(P{CEKxrJ za*|#_IheXXAqG9=U%Wm4X-($BUC03R^h~s-!0`~h7OnBu{~#qSK?-c4GhXM;w1tw9 zK;@Yu8zUS~O2N9i#Qu?TW~~GiUnL7fsC#g7v7Ijdkv?+c@%Mgj0|!o+oo>Z=uw6C+sU)_C3JDV zZFOl{losAT$E`pzE^Vol7T&C&wHV0wIb;`101VeCw=RH@JGZAtsvf%uUJr;aU;zPC zq_1!X5&F%D)KXS|2eQ!S?{O-z&H;7z za7q$^dD?%~tIqCFDfkf4MbxWSImNn9o70o8j~wpggHS9$sQ-B94_Kj9W|3#%{rVd=%Y-~v>3Q59;D{=5YsG5t91h4I5l;k_1| zbHJOJ`OHUaZ`I$t>f_MZS4EWNX3<|RvhR>+vE`?Jz1*1WbHTy9j(XbLS9P?)4X4l; zd^(kkJwq}?2<=-7XP*hcyvis9B2 zG|_{xOP5Ja^@lMbG1kHPkU^_XZSYE*e&QO92N#^;QPF!%7%qg#!5NnOI+FbDd|tGu zk671^he3?z(!Q1VIP5`Ze`euQAH!NpD&N)?R_5^E{5oNr;~QDq zIN~1~8vb&4#568R^}au7Axf9XwQ-LVsvv=<&e1|l)le7vMlHJ3+!$uBCGGiNxoHxv z;GMz@JzX~Wl}|h5DID0ZeU92um#GKxO8CrsTF`!T&uwbvy({JJKiNUz?MiPlnu@J% z1pkrWt+zWG!}z7i8)MxCYVY$e>(LVA^;aTHNUWKHuE3JKBY8^J2`$4qkQ-6ET#{OO zwqp9VV8PJiuwFfl?b&?mi*G8InFq^MWn~qV{S5bU)|`*KMjG>5Y~tD|X2`U{!XczOlvrtgNgfVGNIBPwYz9qH`Ux zE;93{sVBE`QF~wfACu{w=leE;REMX3Oy9#ONdHj%Jq%bTA+Dast7KiC$D?6{N9F zuB*S_o(*ZyH&I?Kq(I%6eX){umYS^27*B9w-@KMJD{&!OQDxNqkig&;U?bo00yOb* zpwxRj)%355bEGGhZZ9s{tr7PiT^-5coGM%zg?rr2tcQod5Vba!23dlm5z+{W7qcVb z1iwwL_B26VdMX7C-{h38nwo81@|@_!Cy3nBcL|u0(D)G}plKqc|E1Xov?e-;mMeo_ z6=+x_M=VqyOAT$kb(m5~9Iz$c5ZnoL6k{+7L42Cvysdjdci7#Bg(qmLsa@hA+pFu`AfK!`-*{B z%JsKJS!r^<-bWqJHon?JKNO4bthB+s)>j9kd1q(wVRr>UZT-rPu-W4+c9?;4$hA`1 zM}i6G6dp%%8TnTh*f^MF#@y8>{TMCdK#O-AKhAMq{e?}7;=l$RB__Fs^?HAVetaLU z8I-s%YE_sbl4M$}zNK7Kc(egh0?o8>t;nL|35fYsXA5l0k+amRBsiM%cJ*SCAet!T zNLrV-o)TiThPCOGlo_X{uCacL#;$%h5c~P|szhc@1kcJ7vrDJ){_hb<4Ul?P3uLcu zypF>AczY2&2i=b(uQ0gGC?Cig9(Sb-Ea-DJ5#OpkQP^g&!~W|muQ>a)vm0V%x3@LdTEU*5i_5+u{nH$k>B|%eGnYpwW?-_P)gM9lMue0h&(GHR1r-OOj1BS=@zSxfi z_XH4yn!?a*x$f*#mcw0eMPRJ68j2fXCVAx>-8+x!wr#O@ zCoXy_`kkZL>36hKQdyP8=^J4d_42(eQWuDHh3_YLH=D`EE#D6jk&sR3@J6O29Ch8E zD1Xg*c@~Z84h4l}RLT8X^D0!UNGUyVS^PDjsuCB2HSku<-p`@S zzx)#1qA5fg7da;Pe%grHHOE8zc)h#a{y=#=rrt?Q%0yY2Jcp9h(#mQDjdNpusJ(>b z^ko>QMN8swk|Zqi#3Rp}2l0!T#(S=ZVW{r@W!YYGud5mYA=__@PuKJXr(@2(BX{DZ z-hOp~efCbyoHtajzdL#rVYfo>lCgh`jus?;%ulJA?FyHC<9uKG)Dqv_wbm~X#VwsIw32K^4G`2tgb5hYx6GzD0YjThNPcf0H37K28r)RJ&V|mp$;oAab ztxX?qW6r$Djd}F|cB@vIYlDWqv;64QsF2NZ)LQ)-cBZ`Atg~D=vUW_zgk}GHi2%K1 zBDU3ROFZxX_$93)oR;_V;FTPd6DiQk z>cDf;;7hJqXN=`}^(bx+A%s2-f7P_+!f3pVu_4WR)V&)GP78RT{{x**(bFK1rUsOHHB|o4nl|o zn3eCp9AA2LaY^eBSnS^s@-wan)%bPC0>q5fNoY~s_v#N=xfuk;&iF{ML?3eks^a7H^HgA z$EnV8zV8`SBVh2BZU_DHp{>|fEHGY&aQrZr5Xq!=DYn8Y__^4wI*C=jBkowFL&K~n zEDd4r1%XEN3acW5y;Tl(ylW2@B6FB)GHs9ofWkSIErGn_(z~=gpw)~#j!M>>HuNeE z_&v1ZohEnD0{lsC$LHa8Z5EAOwd0owuDkP_>4 z*c{B_erMvATgj`P+iMz?o>zN@_T+Ax&zafC>h3o2BepZ!Qu||aKeGd?nl9aX$w3BD z18|&wN`s~oGGom7rBk_uS-K-#on^M06&hCld}jxUw}?1@+!P4YbJDeCy$$x8ahz*B zRT^bn1k^P~W22Je2G;`S4P1V2(o_hvwvaX0kzH*QkY62gF_|~1^=1O+Ic*4e6&mPH z&t)av79^%LZf|(qpa(6v(!3f`WEI>uU$HE2tk22UoQpeaZ-28~%`0j3Uh~IyciW6? zNod%B;$?d*nYD%OtccalDABo@d347Kv|k_Dke4@6yC=>P>FZ5 zEHAV6)IgrK`SGPl=ikp+`LCS1`KN|!BSM15_ve{{nvN<#f;=d-!JX{3N~)JS2hr54 zSByL~)2VFUw$V~@wW_m;T6!q`J`y{{8wm$Y~^d-kybWG2Y{>TD^064nG7FH6f zDq&(H-e0UvapVAfW7mHMC6+kaj8Or>$!puupxK^#I=Z`{k>l*Kn{bxqpmosf6QO&F z*K4OM&{+*8=IbV*2FB<-ouY73o9Qc8`HRa1nRXS#8c8C-XjQNZ=wRshn^EdzwkoS2 zP_yr`)wxfmn!QRgY9EDsT9f#(^u1c1V)|LL`tnL(^u3qrf)m0Tj=FON zQu)AM9Fm}=)V0ODY_f#--FMA|g@G$rw_IM}ey(YA7=KGn>zEwmWt$xl(wps~-P){| zn@1Y3XwqeovoJ#Y^#y=XAwQ@gAk7Knm+n~b`b&<;iqVrK1rJ4Y7*pF`07=6_S_G6R zr~#eTCO?-01dfj3Lr!gw#O-PYPCbvq6^<3Z?4%i$suf#A&-5ym*;tm!FXLWL1R3~X zrB>7eANI`$Zdvmmak?^HyIo9EGtG8R_T7GeB|l|8g^mCG`9>_9t!$gHO3>j)#%{lS zKRv{1yDD%JLdZ5TA?$scj~ExYCh6gz&t4=&g?Hjl^{_?d<|QnQ;E>xf7%*v>8!;{B z!`u1k-Bx+U^xU=o+B8Nie82GTsN-Z=zCA;ein!QirF$wnr8lwcX|zTu04J|&tn-^` zy-L|v!lk=WUBN)ko!USLr;Jm4wk%S`?%XqfX~9M1ZwEb_!*xfH*WvEirNO9uTv=Ns z1GSpb)LH@T&}U3&b(tmCBWb@`L>8zc>x5m;r~u&VJN#967l1-nfn%x$r}JIzqs`qn zd>xtL3lVT<;LR(eJ!MCJEkVu|Ryw%8;6J6+?|^(pr-Tyd-%~){3#8 zSlD}|MD45Ba{5PMbDx;jF8Lj8xza!OtDB!4s0KCcmp+T@S;R!fO`)~AOS( zs)g>)cP&H>6Inu8_#o+}8fjJV@!CVXz#Ws_4OWHc$}^ya6c1ry(toNdDmr=?4~OPE zfJT@LmVr?3<+!7gGIZNif+K7|?XbU@ZFage!B^|oF~MkHH|q-r;-Z6@6{~%cx1U@u z=$YiZzo%1uclXm4o1Q7?{b4Pvvd*c_*0e5k(u?anmHsj7I^gA6LV7R%$S05lsdH4- zM)8iaV6wi&gx3H^)Q*8GTO~JcX`PjOwG|s(7^%Msy}s|>7p`G%7bQ~< zb`pG6@0DNw($e&5ckH-LD2Q)@)sUntzGRwOMdm&8N6_Qd^Q|$wz>eUlr=-U5J(fLU46jI(Zt|!D>yQKRu5Pj2Bm4{eIY4DdUn0IbJ;S*)oz9$G$*Hh zEiQKLp8q*`R=IaqPTAvZZPirk?}Ujno$a4@H27>3lH_CNmpk$0R}N)%pJY_7uC=q0 z@DX*<0Yb)^70mbRaid8A?=_qpq9o4gd^&!Y96dNkrnhekANjB)U^LY?c(mr&-^$aA zCp#&b0zHWpax33{_sh~gz9ZZiAn2Z{M&7@1uDhyFS7=VdsJNf+lp9GyAI-oPu*>!d zmgg+hqjip?HZxp4{$NVQKr}!JkT7Y1qhQXpLiYo~WM_6?pQ&GCl$zj*TA1SBN|7!; zJHq_5+NBQq$#8^_Qoy%?C5Xc3sa%41T_oqMLIZT1Xcwu}URR?7(KRPR4uiWB_IJiE zwJWm1!5cH9{33kakBM+z#LGPVcc$QwN3Wl8)G{WTn?+gTx1*S4QyP}4)w-!pSg6cn ze2=9363OZ=XvBowWq-t&9Pw%k@OZy1>f%c+SWQB%baO_*VIuO1{`<`!S^j!-$$|aZ z^xZ{N`nZl(o}8U8q&L%^+XkOwHlXVg?Cj`(AZ z5O&}XJA*xnx)n!vgAg8(B`FyBMsf_pcu%p*m=zcYo#s>lMh2x4lPuN0C9~@5DfZ+# z`+8G3ZFUyB7WVxx!d>qWvh zhdGKPs`(`*0OycbtfsF)o8;-gS|g*xn4|kX{ajC_Mb!6Z?SafvYPsyVN(CJRTo^gB z9bKLj4J4>U#A7=7UG1al=Qxqisf7L0?n}3=TDr~NVZ;> zyf|+qEX;p}d|-!0B^j)cbxnURAhkP*)lrJC8-VrkKAj{h_`J>)Q1<7~pJ>)?z>q(} zDp#}^^+7sj?4bPzQ2%|U4ZxVn7_r%-EvZdDHlmMHX+9*|9o+Eku>Qb}iPepfFsMs?;m=g;lL04(FqiJC836`qg2$NgqlC zi-rory1)uqi-r)@fn}YQe411Ot99ik$IFy#fV1(-`uCrL_$Fz%>Y4wDnYS%Ar)uoi zS-z*<(^D9>g6IESo5}P5uLf@L56(Ho9i|J`4K)TjpQ{fCd`TCOTGW>ac;O}VSh4$1 zMEdKq0PzxBc>|ad5&TMPN^;F8#-Tgg*5~JfdOlkAAZQ?1hNN@@zdBF-29Zs@+@Q#g za7H@WI#tT{!_mK?FDwH^w;1ZAf7E{170O-5Uy7SVFSK|WF zO2%R+tE?YQRa+}_ykC6a=vb6Xj8Wy^e3MN{1h?+{WbO);%r~U6X*D~@lF+Ykyolmc zcs93M-(5h%A)lu5<6JDr`!XSdD45*Z{)5At@;mY^YJ!t_r_EPcll9jMf4fg!e5wD& zL?ZOs;&%gz?qIs+uKpM0m*O9$&~4K$s0NMO=ajZXY7H>O!Xk|%8P*An z+&WDWl@2p+l>xcAXglnNhC;)p7wcElac9%Kw;ru0GqE+lvho#wOOvB{6Xvxbnd^(- z+40Yh(7I?L1y?Fmt)Vt)&{ahO7cnY%%cpa!&at8hpnAQ|d4fwCr9z&!7Ynat?jQ|9 zJ2z36T*NQRIu;VQ{mt7fKGRzXot4R^6k(7bf2+Hv%3CecSTl2o#T;2lSW4jJ>+KtcJf}LgBQwzc4bn1Hy@SJs7~e8*kR0CKfk*lIw_N~7*yq2 zx#O;vda2w5?LjoDm3x)>+7m0EZaKS?n9J3Mv0rJh$sx4FMBXan2I_pwUZ2&P+=_;q zB@UFlOFHpgX<*hs;c56EGj#}5R#pA~qKI9(v1cEwfAoHF%fA5R%{R3$>n;@J<&d)P z?NTj>i>}cviH>C61tR;6tB&O39@#)?gxdNBXdGMxP`aobeB&nfTrr65ckP@CR(@iU z&1<)Yb+Ufz`4x8IEG2nNmK78JYX85GBC5-y=`dSh=4pwA?h)VcNM1lM@w(9E`6a=& zTO7f)^{0ZiJs%p+^JQpCUc?ea4OMGJ<}v@U<69&9TGaQ#oxT3YG$ zDL9(%h*FC)cwgZC+ud;GsEW=7a{+7hD(I=;L8<8)f57Z%;^$ne^zzF|h-J)1OZ?3Kz}nDEKH7_6iT97}A&&;8gohfrp6tv&5kHv4@Q+gZJ6?iIuqn%`B5 zRmExPZcxK<+~yiuJIJWGi@Fe8FkMljK3=t}NK;tx*Mo}97H2(KM@5R^pWILWI`cr$ z%**|aD>AaIYL3;uf^8OGn{hfP6z)gv&OTYFaS!iB9t9T6o_g|VH^hFflI9W#n=ly% zJ+0lNRA;lk)+4z%`8EzCe&xe6XXB9{Nt?@YBio7bdlpAkotzJpx7xY0sucoo-iJwr zHGF`%)5Q>pXQTF3%h|3o0|-x4EIZVxtjR5k)en%lY+nwL%TuO=v!pOw%SZ3@a7y7* zVG;kl_g-fsVZCXZ`SA+!h6|Z0L1+0t7C2y3e#_TUM&m(2CF>Op)tS?>1aIer4?vLS z*sdgM1Dv30e^sNxe_-s|Y0X_UM><>nYh-_L>a7pYtZ4%~^v;dKd9Ua0vtuK%KzSX0 z*3iO?fGrGV)-`BdQ8UXyIGn4T=S|>wJ!6#+RR@1c0vhx z!_Fgr5tnhAt9+Z?)b8eu;%`roXUlVL^dYrgU(Gouk+kOxN_dcB)qW~v6~`5}eMsd> zsk?|vaN*<&A7QIE&oBRj`z{XBj9KpE9d0-aetl*(qsH2}&9oxqo~w1mB`(&S5}R+-_7UpK#d|M}({j*FbCU*RW`;1FfwwGwca7(R*WLpha;Fm;gZqu0hO&w7YGdVeV`*{nG^(LnZj~(f_c4=zV zHtb^rbdTA(OW6Kyw9a)?#o8d%IX$F9XqMziI%~ho^2Iyr8RPJxN-Ua?Pxvi238@e% zX=!(prla1=MwgG>Ho@C2iR`1K7R*LqVNHJ5{o4dejU_m|zlS2MM^LO+&C=r@bN=}Y zO+s|~h>^iDk1bnP;RWY`R@4yPrs)c0wvaPOqx}>1p(0mz7yeDGrKxnuujc{7NbJjU z1}ILdD>%WZW`b4mB1G$2K)fvMD$|eDcL(S^=unm>bG{ zd&vgwO~r{(`fI~K4uoz4t>98!9Hqgj>S$8{N5c^0Kxy+){cYv$eCJ+>R>5AIx3SB!*E};Wm8?OZUVORO zy%)wOAx--jf2b2n=0ABGmO}B}d|J!Rnv3f8_hNIGft%JsS_HTkXTK0Yj5KVVANtl= z9k*|~>5K3a`Efr-aO5PtLO1TU!hR)`T=VaE54ZQaCxWXI=%>P z-(CoTyTz49tLKeOSr=Rtu>_5CXu_hkz$)$wx&;kD|Gu~tSLNJ81MF8rxyV#fuYWT5 zN`f(A!nVtTtGIg2yCeV{X1~^d?76!s56!0vJMtvbVs;4>@f^i(ODtSZTT(p@hDCVq z#Jt>(Qpvk4P*<^^o{%zGZ-YxsBN3$U`uCNkw=`bG-kw zdOKz{x|!Wnqc~s#RQMU?t|WPOei4xY`9(c2D>j><1h~ctQF?D|yxHlDGqG-pVntO( zr&ZBB(s(>c6&0V^D4^#7{I|$y?aKE_1a#G=@HDS3$8)R(zyDxGEZm=h%9ba0Ql6dQ zm|ym?vs4x=z^Xro@D#vIIdQA`6*`#bm9eDht;-s~%iL@6aelAXUbG zQd`WRv7wVWTVJzL*Euc6)1$jlpwA6K11|5bLTVJ}>Ww%wakEh@KnAu)X#OqFAo^>D z9;Zr1cG*cM1u@Ivbf#1ax?1XG@~+=T$i?MlL!yl0S+{fHRb4w$YDh>-%_B31usOSY z%3Au&ALso1H$_vL#LnWtD;nn%_r2l5C`+w^MMG=bY5tly9OnY&+1@|5in=Kb5fDtE z3xE*;-)eGJHhUkf8|7&peX-2f=#QASj#5wSp*mQZbLbqqoOLwmR@TZNiNAKhh7=~4 zphf&ePT{P9Th$!bO2ZX7d7oE%_e17#2E93*Pw4a6-^vr!B*&dyQF<4gS5&K=@$5=} zy+zPETuQx0vzj$8F~|U^8faGczqT(E9DjUr@c7w+-_>cI>cpJ@f!Sz|O8lFp z-RW*pK|5k=9(1^uJiFBDLAY3uCtvWL6?BsPR?KB*wu~8Y(Gp{$$X{t91QI=72kcxT zH4|y(g9ueI5kYla5rO8g^nuIEx$J?GP&%nVUE#nuNEMrQ|iP8HoTF=;@spuVDV%I$rk zNojGeco|3vJM8W3pvJ$oQklS5Ttjl)%1 z{BUqo`uDiUk%9TeYGfb11UW-=4P5>r*BMF1z?~a9>!94n-Wu`$vG<-qQFYz6aFax` z3WzAdgh&#VoDl>i$0kFAl5>s?Cee|wZ`JMck0`tM-fOKH#+-AEN0Nxd&o;E*vbgrOU@(=si+JwKm? z+;Q0Km6sJWbQtcbiRl~-LGHb~`$?k1GtzSX8qwlexO|QTJFRx%j`p?fa2RxTH9RNy z-odv7MBk^B2sG(Q!PTVULVZLO$x%DuI8jLmq3vRp_A3V~lT%w9#=uD;I5<}oqGcB)VIUc)17Z|kLZ`ix(*YDnYk2N2?j{t6S+uC>Ai1llwndi02o9C{1=_!px zpsV9sPC6B>K37Ty!XHMFV^>tkl45Fr5X4OTvwI(3XO}o9IpUx4;<9-uG<(nz19jPM zjB7#kHxkt`KR6$;JN~|nS(a|;cDV;3D41fQ`IfT>Ar5?YlL!X`?9X(UP8?awI#-DK zRsINv73lab+~p2BIhT@Yo33g8;c#%<2>xT8bj{uR;$!W^W44Ne#O!_O5f($apL*Vkk-HV#)t84FlwCxGj4LMoBs^z zYm$MMns}xThC^rBFzw$6hl#D(s@2hU2`f4%tW2_b8Y4AJ1#9;#@SGzZOyQH6FPn-E z=^Vmrh>6o;Hp#s@Wec{$B6+5NS`A0%*lVm6Aq#f@!*JWc;}9Guk^*B{6q|kI_06sxtnlFk@}b|pa>$^mQNf6&qkZ*^K6}EB zR!a1fQn>j1`ne5}QKQQ2`I&wP4Q zk~Y)Yqk@6))fp~!jqTsyK&$`Wv@`P&%VX~~q!Qn8!S7`e@ZJ4jSJsU^B9iVKU5Svz z<*84xiXCBXPp9~gn~^l(=8raBMPEnTftgWp6&0rn_TqENP`b6WN^TzQVtake$D7%k zsig(e8ya7#oblO{wgcb?hUqhN!{*5@wv-|FOh9~Ecnj{*@q)tx(GpcRcgH^5Yd0x} z2GmPhZ&^P@v2BndS=f>2X>@3usO0nq&wigMY#OO|lyy9jT;arRxxK{WZvXxtS8|NVXT&DWRt zT>{Ab#WiZ`&Lk^hHduqa3-E2~#Fl@9tl@NrlZZKK(&?Z2OWazhreIjVtn!Vjza}k^ z1XB1YullxEx(&eJ@H8sS>0huHAW0n;kQDk3Ho`CC|~30ix%J zlt(%JIALUE+wEeE8%7&q@-CwChWqpTW)!a#&Xhc~_9`~>+ewHi}iHcI``LZ{h z`BqGLh3F;My3MbyXJRMxgNTz-(=!%|278TFj$A~=z+WI*fR?Ty1YclXe^+By2 zquVF!LL1k0H$?yLiQFI6Q0L-0`w&W?qp=}ApdfiFVmQ#7 z#57)KOf2!y`_9J8P!wuf4TC<;UA6j+ZDVIcQ;%(rf*+`_A~cH zVS$>+K}hd+v@ly=<=FHmG2i!kDK#2eMrmmNDOs5p)0_pVI?1I@sKCt>llRdQ zDl)9oSxciL>{FU$=-1)0SU;0L;;PO1A$%E;8yB@n%tLrflDT@YUss$Q=M$3Y&kR&m zAE)}a*juUBFSzh^pEUv)Br}s9ZF{h-Y&$xe`hyvxKU-GmK_%!?z?ys5MVu&E`(0FK zel?L*Eb3O?TE6z6BT6}h_?A|!_>=))j;_?4FBF((Y*_B~RiV-TZUSMrjt}t>hDd8T zZA11Bh0^#cmk9U_E0KWEW7xBMoUaDPaxH}ORFltQ^FD`aDrS;Od;2%?E2d_Z=AG|7 z0kxxgDyV=R4~t&BcCGlbftJr1Q-19>ffs4#`leBw%W}L)%(I_|!CGzA#e*H4^5R?F&H)tugVEQhGFQaG zs)F6TJ~N)|;2Wcn*K)ck2(yyQB0ClzeZiNJ=EkSnU&2%V36dk|25({co!)j+_3t{0 zLPA1-uoK%umyn)*M($L34S@YST?Dkc$D_wS*WA^&jg$UxPZa$_N2ck#FOAkzddV1D z+`YZ_j*WE9GgpdRVr{|$p0#?fvr%&#$>cbE3{^HhMOtoG=Na+e_E>LMVZLh2H{8xt zxGF}lDg%(tyI&nua5jxo6AB&VX(>*6ZZOO04_G9)U9Y|J+^eFZX}9ox$(iC@H3}2b zUt=k-EiX*JHd^tC=44Gt#>ii>y)sqguMiVOQKO~S)4WRVDfRL8NKNlUT2lC;r&Upi zur9mMsY>as=!cl!9Lh6mzsan}t*hsC=EdA1JBl&k)B(eupZoHPJMn-yk==cu6F@U>8mI?PSf+y8b9vQDux|oNT~#{tkQ1-?%;A z7eiY8^)0mCdkECB+PqzDL&qckJeW_KSPf_>+w*PJ;^e1F9WIHr%-2{S9p`XZ8)C2NA_-}1L{U`Ij2v8Mh5HvR5SyC{_d%CV z>9RU0HQQTNC_FERai2&5!(4v8{%%a%SA(zZGxT>)vF6lSn_#FYMBzK{aLHGQ?-rHdb-h2~IA+okUsiODzH_nmceN6xY zdIISuxB&WOs;wx((bqyA!Jp0cOs$EDT#w3Ks}`A`UVmW)RX+(F=MZ()h%!W~ex=*g z*qSP%*(^F3Q)Vw+bMXkBE~V#g*APo{kWO##qs8n#m6`Gut%!CCzQSO17=fPlmJ$*< zMY`onO|EvL2Z}-p583D3yfOr$a%=~h>Y3BIY^ebk^POJKAVM7IIM=K6abb+F*6h{x zi~PDjJ`I}>74o4^Hj%&&kT2b<#CUax%xHH^uKEwa2dQYh4{D~$CPEy_;bW%I9&ec` z@$2qS#oA~Ee2Z(Te{yIcMf=qdD+>(SrPQ06Q;kSxzqIpUX;5h?{3(%K@VQ}vDMcRT zFV#Vxn!Lz&Dn%%1?W1&m!pInx(HMVdYOd8p>B;yh3~{TSw)z|huYofwZ&qf+ytS2Z z{hbStNt>1UcK*9FKgsLmW>oHLwLt?x=zPv(!b;J)v~mTe2DRhevMv|KXG+;jQN@_^ zqX(w(8)3f|lNEAJK^(eXBO>ywoUbM4D=f-ll3QgD@<@Z`Q{nz8B=yAp&A%mB-aiE# z-hdUTADAtN{7wcx4%q_CiU%m_jzN4ZkQjZX!4J12)OHe?*)i>_aa5`;T={j!tnA`z za9Ye^fH;NjzE&7?bfRj&afmWb+EKJPnsrlk?bJW-Z{Olyu3O)SR9L@b$Od602@yrz z^av`&3AwW*|K81(P9HxL0DfTG6L~9&y?@zY3Ook)=YMpGykK36N<6Qkp!O5dMQeUm zYwz-B_Zo5!f$!w$zF=#i{+N5zOfS#NrLm2$U(yJ&bQraaNEmMIegZj-QC+9;--_jQw_?`NLsO5e|1BSIVkUqfoY2Fa4 zL!>ob!QtBb#0DQ!y#E#3+DP_d-PGeU5B0+RgwIt^T*9;yD?{bOYvjD@Fp}(?`hkBF zG(mv~;LYQ4KCz*RqESNO9;fi%UmRl${$x<;wD{)Q*=+x5#j68-<@O_{E27ToRZ3&AWq-(L zYN6TwPEq4KV-UX34mTneY|dY# zRi&sc?0v9f2~f&!u*}C0v4F4?f!;rlg3nd*f7EJs5LfNo>`|?E|N4h3JEt~=v^4q! z6cEfzYiST;J_VxEdffXA7f71e|7yRaFg$4kVlY*#Bc-`a#MpDMi+YEMdSCA?YggQq z`!Pg_*lRo5es%pA!wyXB!h$4>3_BBN{xGQx#4+80;kXuAYRgU=C z9^H#W@mCC-&*tP4g=D_UG;|5^|50lNb22_h&w|cQzx?e{+9P~%w}EhRck9;34l7z| z3Wz?OdY|S^O?ehJ7}|R1@V_zg;4Vdz^;OOoKYn?EY8V@{u4#tD!tWra0@R~WCx|u6 z=S2sGnOm4?wyB$%?dL|En;%F5|I~Q3+2?^WrD{u@$ivdzov0Ka{RC_7qcC=EFZr{g zeK)@}ss;gNM_!jO{f!36W>$wUQd|XAmg7aa4YJN?P1hwWc2P{oz}7OJ-Tjoh%8~)5 zHU94-yUz z^OgWTQfT&i&r!eC8bxKPp8)k}wr4+^7oA@}=oFtu=2RQ7PeG#u{L}vSg%9u^JeIL( zl-tWKmbaJm8k|d-IT7$m^yfnOpEfdsD)BO8<8!_8Va3`z9STqba*s@zA^^n~Ai)7L z<6r*^PM``;fAN5jPUR%6CA_2=j=@D~#SLh03$U`1I2u1p>0J{+XENF2S$`cQ`pi}6mZwYmj{=Zny zGsQIB*G1${Dx2Y>Gs{fw0&Asg4?OiJ3lzt%O(L6C@Ewn@Sn_23^Uiql((zp~?3*nK z#v4(lM7qIzLGH>oCp2hKo$^h`Yw1;?RnSe;n3mZvm#ck!F>(1Me(|zZMX6m$jh7!2 zw%SH2-;a85jl@Hb1cdO|-W9G5L1IfQu_n~pgg@IRL!{C0NO$c)GeFZ|=ykc;uE4In zEnmVby<@SFgZ4VrtcoBwNxcxQPDXsY%7pz_0qvQ$-na~#4P3@1#Ky+>jt4?b01TC< zY{P#PT_5S8J^QvTcYb-gCMwk@c;;pIFe%b82cI};j7qFocZ@Xq#aK%lLvIyDTY~WD z_Wop0x9CM>0-?cmctrtkINg%(C8U)xv}P?ZstG zAeG)-M~Z~2^USEwKjkl$yJEhH+J)Th6z^dOKnQBSP4Z8T=szz{mM$q8BIeeZX^Na@ z%e#>ZG3XA)+chiL&E#e_50?BlcpI(N*vZ-)ir@<6l~;Z%k2uU(=^0o0P76c8n{JVC zU>2q|59dYD$|Lp-Vud4MlD{EcIuSu-GY>iZ+CQcDPbk z;v)IntnM!T785fpHpX_fFwKM^x%4-C%1-#262Yh(*g& zHG$%vi=8zel~&8w9M5;`=E&^%{>m>>%~8cFm6tT`c%sJ9Vex`*!vE2lnTLmfU2>qGBPk1qN*y_CxVbxo0y|F}o z$MYXT+Eef3oA%;*Au`&O&9m35gk1--dVbX{7o(mzNnl1_7Q{bFj<3<4>YAQ1)jw*p z>qqnqBn;n!B;47)_W*qz;yo#*vx{pJZ!%WXjceQ}P@-}~+!1tG>47e6=g$6wSx`3H zap^hDPUR;bsdx#Dn@v)NP(R@_bg3S@?)&AaB{x&bO#8I$D9xX)s5GRG*jV3v?v;_Z zv70k#;yGV0CC)kzenpX30&+h^>u|S1y zjcQ)nl9*>byBPZBk-(JSspw?1o{_V$8@kgHH>7rhJmk|St9KQbo2LLyIA7xrT~B0w znHEhhH>6eW{(a@qq{@8%+5PFv$-ityt=FVc>ye!j8e3I40MS1+a)=i224hqb-lt-N zsyy5RCGn@v{I91I;Gn48*#xui_VaoSyT>_ehDhv+{?_uId+A_p48e-CkT+|=5!V||F3B2$0*dlg1*TN5MC?adB#bN3|?K&ulJ zNMDqb$&%1iJv(NbD53%nmU918uW3c+EjA#b z<n0$M(wXY?k}7#sEbv(A&hi``V=Vo<$UatpCn00e3R!)Nb6` zaTY1^*dpl6J@gM(Cr_^Vs5FEl z=|N9$_>J&!GA@y1VVjT)mbv;blFWcMx>~FmUUL~6B#%~Vto|mjO@Ji6ES|0~fB%9e z+IeT*Nm;j>{QZH@9l@dP;FsA_pc!gtVnPwuWF_goz~}%#sUP+!JIgsv!SlC%#GK8) zCu#afxQ-820lN?n<$LD@61@~58~nEYns1dK6W(0<1mfR|E-m9PyfWdjJ3{a{rkRZ$ zd+Fq|zh30oa*`yA62bM9+R?+2jjo@R&WMiLXV;_w zwb1BAVcX>_Yw0Sp3;7%3Av+1{aj;n659mz}AJGy zDOx-+VGw^&Sc{K4zm*lRTq5@F!27<0jU<8ZIA|6lUHPcF&CyTLbrCV#;G`GS>A5{( z(xsuvGROtQT|kr8*r&FN7?maP#JIgC!b4P@mz*^Dc!3Y^h9on733riqElCqe2njx} zx>E}LdU+rpZ-=9w#5b+}%aSn9B;VXNd9tPpdn{SGG2*Sst`vOB>f0>C8v+(yd;l)b zL-Q|dX3@p0MuGp86Z&&*O%aT^Q3v3_e1-YN#hfG+ z-r;Pm9b>*klXm?d493QWR8&eVme^M+c^%BL%S$-ErrdgLE*C`G;mF%_+$8A$x@YqU zDR7(JueG&xSvRNRqbxnD4Na7_On3h-FKG$8Q6mFB);c`PNWa_A#yx5|^u~;Qw?r(O zn_UH&>i$(z=xs2b_q2820(K4wgn&A3ZpWnp{4yoMd@5=O+|O-CH|Xv{wAc_YNr(C` zd_}h+?UGuC>|XV^m8_O{iJqhK9ffV375EP67@^L5*uW7YRnfg$yPOF3n(IJ$=1JF{ zPM=H>ML9{yP50CfK;9JGQZr8JRFV$CO&cIme&x+uXjvwFKLfW9Jt?O-Ke=&y{j+@a zO&%#_p^+cSf2une@5H9am-j8ntMNu&d)1l;ywJCzHg+TJu)=wS+mP424b1gM2V%e3 zuA4(Sjom<1@#76?0vsOorpjWbxy1Z{Ga%~kr>n*lc!H`g|E&dFd(%zgNcC4ttnrGR zvkq0ERx0oM8hXBy4=|IBU2Hx3wuPPF1fT6mMl61|deq&%GfE5w={qGH)vM?*6N~N!So&o zM19^QHNBRH@UVNwJ}@qL(OhtU=gnJjYkPZlp8$G8+$D8?ZXSRdbKNQ)>zp!VzhBUC zij2@W6#Y}PdU|>nzj=dZ0)TeDfq*i0iVS`Se^&;GGhM}5cE`WdnGqkWbIC$AA<7-jQ`B%4 z{K6U?PT7kq-j-`x2SW`4c>RQuu&Vg`<2ZbtJOYyVtvgZ0wUJp^+1>i%eMmvn%li|N zJ#A_CaJ$0mj87)~M&o5CZImA5yq)_I-__4}a_FqQ8bE zv2j$_<&OilUOa?j;PBx#s^QZ|B24Lw!B4^ks>X%%-TR;3B+@b4-%~JxEiTbhzfl5i z7Hbe6o6alo6uPQ z<8A5G_j}*rPT@>5j)KsMXtOtOjodR)chaLk5p@^;;(1k{J$p8GEermA6y!6YfQo}{3JW=bk@#(J@24acY${#;Cf*Vm4<-%(s8|EdAp7~o zSNAFV;vBW$Cn{fciAUf^&xW~6exgHI_LFdrGzm-tpe!!$e8sg#dcN*WL@CB)XQx0O zqauQIaTZ7ac`}Btlfjs`12YL)qlNWd$NkniU}*XKmoeqfw&zN~b44smcVf4Dv_~J) zyBQOY$31Y_RK%L(6CmS^?dg9@kKcf0^J}4!SgUu!t3SzrsM7wmy2sGVF1(1#ALI^hRv8bb8cn~ zGcVl}N%;>>i}6DO^@Ur8{-=9ZcSb0yayLphAI=cYM0`q-hl;fJF6;>%4QJfv!Yizi zr2p4Cu^)Ig*k2Y$|GKyLUIOzB@HWy0j7yQ8AFvRe?Zi4a?wv1@Fs*PR^cg55nfVhY z@Pj3>`@PASy!i!#(>tshoWqo8>#IEZCU?&C+Eu^w($@}Z0O>aUu=d4|+Vf!m(Jmi^ zE~^J`W5fd=w`reU76)97P<8e6&PR2HtCA=Z08KOGL_`bEpCijGbJM(UZ?+E**ix<^ z^${#VjgGG@0a8J0@H(;$FG9C>w^<=TMan2%%%>71c3>cr@q2)_JvRQ#voS)c6M9%C zq^$RVhC+x51~%xsomy6<3f{3xOF@P@xTxz0JYV_kpry*n$^qK# z*nn`uoC!v%ul{K9cQa}GwFxX=YLS`QxAmU>Y`a~;F4lNEzo5V+@bS(vE_(SAG-Fd- zBMUSmzAFP-uZqgb?BbUXG=17VG`*VV&?-mn)>99IJ3b{(5!ibBM>>rWEd|EM-vm0; z*z*gr3qVM&PqSJ*7q(hRX(y$&-X*O$`)($2o$A%c%(M=7d`Hn|Sc5n+@}GdH5|A6Z z7E@2q2P8Ra3M{@S{hW~AH;SlMSTg?bM63xrZ1D+*HvRhzJQ|GN1x1z4J^?`AZJ_uH zL+C@yXhLbvgtD17vNLfe?I)O%xZETOb5*9hXtv+DQa>N9Z~gN#{l+!9q`|bLF9Z8~ z@4?xyCTjG^uDKJ+r+L5o+Dl-^xrGlxFB~ItK=(B{mxZq1yUYD`TwiIl=Njl9{w|jS z>H$iZnV#Ya-sx1X<-o)49PH*PDL>sGUk$!x-&=0gPxJA)u(acr!!Vl~@;OTmU|Vsy z7C?;LU$TjoPVc2JG1m|6)|SN{yT^YOlSOrb$WIwcaPD()I(K`f6qrLH<a&~_h@ z5`1&*Xqe^)e#uY8(07?-lb-Y>I5#BSnVn#t4`j_y>m>F-LXk>I`Lfa0H++Y3?yujd zQ`0UzDacZGKhn90uOt1R9&zIj@q$k2_VwGcNzNT?q?ZEM?~G_oCNgt4U}&NYx4GF= zUrJLX{~BMn&~HC(?W?x4x^5gb{y8g*jo<<1Dfvz8@&=cXP(N6T*0=xt^##+YU6QfB z9qf^6i;zhETJ5>|4Vy1phc12GmIksJkb*8G$|QYQh~?FKo%lFKGw!wCvE5zzecZx) zmP)NGm}a9~l3}-l_6U;Es$!IQ$*mw9o= z65-+Bq%Wh!ULQp;;ZnzexBZ#(%U?dFuo<6+O8gyuekQe)Ub`cW-Y^USvjv`zX-o1&w|=c00xMOjC^+V#D;7OyOc}A%*d5 zpZ5Swr!pWoPXxMs2`DVhyw>TchNkc$g_pc+uj=aF%c-MZJF0!xm&inr?{IN9q)_*A zGS8wl&_CF=Qn)W;-Kf?gRF~iNZsrf^O>1ALABZ;eLpcSA4Jt+Y7IqszhQOxJ*xPEM zs%uH3N6Sz>E|Jw+{cCufckR4BrV{rG3u_V+ z89W4cXWugy$Hy1XKYztHox1>N!Q!iWNt!dPa`DU)?&>fB_^?5KOub%ds7|Hb4}FPc zOzPF>V{FjTq!%miOpg1`g?T}(9tKww5`Mxm>es!*R4Rk zUf4=WQ_%FEjGxX-Dhm^zJy}E>j9qGphOQD$`Q*rPbt_-C@Aka4Lo@{pYxTD0dkh2z3SyD{Sm@@XZedzGZ~!2X1fH-%-Dz z<|Pki-f46wj#|u!iGnX&Vm%Dznc}>1x%#aKDpBaBgkQa=;vL+}+lBi1HHxqvE@gxp zd40@u@z82@5C?t?Pp(Pp*wR9u(3rezX0?7R6K=tf_zF_S##k%W+9VSx6=Yj+R@T-!_h1=}An#5F-$!;QNA2vlHE$N-j5Q?K~ZQ zaCm9en{maqF;V1Xt&GnLZ5qlT6u|_;E{WuM@Jxb3qi%nW3YMaH(#xyRFUY!Q>RA-e zIUCRk0EMBtwbG54b07=8w%FhBkHqkJ@BSodylJEL};vaiwcqSp8 z27ql?cqKPucTgMV##jYL3rv3Ev8SBIi_X8c%6&U?z4_H;-r!VEO|2d0(Q`k^eH(uz zTA$7)at9^>`$Y5Zco`=S+-5m8iN1cc?%=-~JcH$$u1wPNyRTKH$&qcBm){Bd0_FyI zHT`*Z?%3f!4*pVkUALLGbW=>j{q*VLX#-ka)?6IH_EW&DgC@!U?5Lx&^K}?EHm)%~ z1)WbDwF>^2Ip)d76U~%FP?u(-{Mrq%=$9)85Qdm6)8Iknx6S)T${l+3s{5ylo%Z=r z-d@@XOw$F$wH--wHl&7E;n)BNa_h6uZ86MN%VgjH@Sw#UgjGQUprMPs?hmb3n__y} z@ux`}WymGDEu~-Hn{1;hQ@87~*!T)10)av8P88}l?8r?`edCVXd#3Hmql^8|h#50+ zsvwk;cZMcXe|9!zlzvM2X3=$>R})F}!PGkTp_s`H#j$|Wn=$Qvwv}r#WIl{526}q= zhVG-SMQgUQak!NLS__GyJmkm!P^&2F-(}O=sjxZ$YLEKi-klu9bEILEmmw3!HzOp=>tKi$J5Du`2?s zJH4&?WUB_$Z%Ddh^z6#Vuw=eJTuf|SC#9h% zhjJ3rLsAL1MPk=$y=n@njJ}-$`L)At%oHy)Q7P+C$YsG22qO~0aQE3u-fW&U! z_{{8>C=GOs-;(W%9<0{cpI&&WAn`>nAdU(kz3a&Hv*SU8U)I%ovb}R;xb#p~#BR~p z6Y#q`etNBxBHrMl>{y?r)_nlWH`NFY@$+JAN%OHmmNMau?AFIU$ZRNS6dW(K*p^~p zu6^lV@+_nhd$$Xi{**IKKwOFtX^R2&1{dE_G-K)K-A7D_8-O~S{QYZr9Dklvi2LNA z562wylzrl0)|(nV|p&d$ks{}7io z8RttU?1>|Qcwcu4;1~CtXqW&A-a>j_e)ZNS+CeBPSpGF=j;m0Ah<8a-UsY>|bkx5_ zem^}ZPY5X%yG)VY=8@vN{~PeAF4<3CtP-U5i3=Wx+W`-8EugBe9U`$O%i92cK>So~ z-qz!Gi%*^ZQj})jWgUqKpsxg1Xn)TgJ!uWe+EBXb!m z$usE|-~cq8P_w=6_X}%BB~+K?kWk~E6yZCuf!5k4LUwQPs2cUQGI!UwEzNdEc zBs3g@EcX33mSEetg|#xJ=kU1l-N?_)!?p!L3tM<8H4v+S%Erq2-W^vVF}9Q1N_)?= zvVY&uxt%3MHY1PY)zzYEPZ+evbBd(7F76iPj*1vE@2>1N$8HK>)8pbRJ?Axae;xYN zx8_x44-m;wO5j)WS+AgzPQsmX9qolT-c^(C{fR;@uE)zc9w-ui6Ngrrll-kzYE9RH z`dKlCF*sh6aK4VV`FJUHsnJQ<+M<07qdn9igA}NsW&xdEP2ih^Y%Z3$clwTJ$2YcG zKG-GPOr81dsY7;1*J;?)?E@@NY798R_jIYQ@seyWL>W-#mf0j<_cCQ9W z8&-qqH{j8o%tu|Y$wOjiqsMK_Lhb9;`IEd?@<`ve+8MAor?>Ky))+div~zR8WVi0 z8RZtBq~druxk%%=<1}yU|Epw`qM|;!KKe!B*(bhN-tdHIIkM!4Gv5^IfP|-0UAtTH zM+e%5Zcz^uW1BEW7c1>E;zIcYE3$CVgaJxo8+v!yhO%o5&Qdy*YxKP|{KX5s1MCpt zENLa?%>tm7S#9LK>cmFB>UL`!lur13k6o+UVrFnBy6F;Sb2c4T{Q>A9YH?m)6>V~; zKC+AoP5@eD_uF4nMDA~Oq+hw}9qAh2P$FAR z-EfHeZT;BUUSbBvH~OF3Xnw93++|~ef~x&PU8E+_xyR_%4a)T=J>Pvm)%qvRlk~?! zTa=A*x_h6@rhVdRtX-9hF3t%y7zZ$G;4OF_FuK@ydTo^l8k3fW3+%a5t=k<>GE-YYR7{61~HB+Q0C)jyKIIz=#Fo9F^6? zDc>h}4v;i*m`?k@T{BDBt^KCvIpJCP>PrrN|x6=CV@IG>{e36N5RDM&4O7&8NE| zt$+7XgLld<`n2>O>O`zBdfVL0%q$+TBa3v6VlLDtfgy7K%( zxidLD?*Y2<@%c}qXXH}u`2y2Bt@`rfp2=%N*Z26_s(==6(UK_8U>@4S)g+9o>G`a` zVbKUsj<+!3WEJH-Hw(Mg&7lcjTbFkEc%K!cCm-^xH&FCYc09AqLN28-8_)tVc1%Ye zmA2LQbU$7M9P_j^G`$yzBKeC442to*?OdPv?8bQc1O#%5A1mA!JMdu7gf@9szthXa1!Y547v-wKIWCgQgr)YR12b8kjz z8!h|Q%x!xD`;UcAzMwQ)8URSNht(D2;^M-hFH5IK@j@@47i(MFwR+Lg zU5*M-$M2-!vFq@NzvRWLP}K;(XVr0Z!U?f%ae;iLQz_g&XN;%>uEcF~b3ccFbv}V& z*l+s_+c3Fa(n47~7bfD0m3eM#Y&=!hZ*E%z6jz$FJ)omr_*Jhcvx-xA+n7Pyr$mZB zYPw3Dra(GS@B4H2r?q`bU6`r#^t%FE@$;V*A(an}F5zzTIFerPczpUy3%9u)fx)Q~ zKlhQL6D{hvB@yXN41gmoHRv&s-7dsIRZd@PPJPrPg|p7jD*vv>rK6*x+L-_{Y-U^h=bg~yIB5zOp^QrDxfP;E6 z_mn1jR>AazlzKVWTsP>daBHR2u6F4I!sq{Pq7uJYp=R@s_ca)6D=Yck(())9c3t=k zO2Rve;c6Xhzg8A!+BcsN3j!`Q+H7g3(+|OBL^h^K$MA?v%%q`(a3si-Jq)eO!Vqzr z7s_iTQ*pDs$dk!U*RCgRmHX$5f!`m*BwY>Rzo29JyEIu)J2*6Wz1;Iu|H$1C$L2v2G@kG{0x|tB#Ma4ZiXs z8lHc=JYIkvJID(7!wLVZ9J?X}EcXl%<4g109c>4Wqh6WPgzny>E*E&W>LNDw#tPHM zJiQCdHa15sG-2P0cMIUIUAl`EUjpEP_4Pbd7fJF-rD)LTF!dT2+oqG;55wu$@PE$8 z8y@@>ZaxTY`JJN1Pt(rki7;2eRa>3V*K^z%Zy@jUMUWV8mZVfE_<)V z2U>eSuv@@Glo>Y^wle=Z>r~9kx-+MwNQKZvEdjh?=q)kR(j}9N6#ZE%=T}pJp}7V0 zN59P1&#x`>&>ZASG4Hu12k3CC1eg?(1X|pv<&6HRFll`L@~2tDzQt(I^c|6j{HcY* z_&-)4YYF`s#<+^wz7W&9QLboG=(E`{yiQ_NYKlc8e$wVk_=bSKLasf70Lwr^$M` z(Wfb0kYlA^Bpz6^`S?Dt@k>|}_pg|@hY^$Rb|@I&%q`_G`kLcRfFh~vdI76~B$kX9 zT+h&M&m5>%#72?aQ|s@hhXCLKd-E+i+Ipx^7u)d;oHiCSBKLi8832T=DRAepYjVHi zW%9)=h@l4C`Cy#YHWstG*J0x|Aha~9{L5MS`HW&SAVCUlErnIT(AzrDyn<>X_n)@R z2zAAtPl>W%Zrr-x&_bipuE23G)$gDbK>q%_^}Uza=9P~~ zu>iz6;WWZb!Z~P7X44JYwc&MTcE{@c^k8_@B4zzd5jaUKRM8U6=IuHkrHvKJ9s;5U zlTnC(J!?T55!#f!Tuh{gA(E<}KaY4eh%qUc zuj?*kXFrinTBWN|pl6x(Zx&1WNIzBoZyLAp*dyTLsU?GFu%M}#&RwgT71XGlnfBR> z#^2P#J%LYx;x5~-b4w~}CDE_IYu2)u%@|f}qn|z%Ys{`1)^y`fzWiv2-V+(_U zV~ZKWK!0R11ofY*@tJy4J0MTpt5~;pdL%YUo0}gDCYRQ*KRS=8pR2mL)i%pk_~m9a z1>&bbLmjH!`}FE4_vAehonag3B35hI?`R&#sH$UCYYi^$uj1-uLf3J-s^tLCDaJQ&y8!)>_u#{fpyf6zc5RQ zr=Y}7Yz00{`k$YIo2t-t<3Sdod6=|NVZ{3<(|gyoD7$BFx&7Fn9+qQ9a#rxytR5HB zoN+1W+t*~Fgccb!-zXlKvEUd-r{P*R7=tW@0FM0WFmdZaD zi^Ra-+cMgh!-8q+ZQ?Nr>+GAc-6zWk-BPr|Q$jf($090QCWro~%iV36!%We7fen>K zd4J(pL014naheh09=Rkfj{P4jEFC6s=IOgXY5|~)jd>8sF0L1L#Bq0uxO23ZZQ!9+ zgb0PN-V&uS8``onVm}!j2Ubv_`=GmtrgF@+Uup8rLN+dE!-aZgcSbnB@`5EH)M-G=agM8FpvEm>aY*LX66;(0kH(p|p_sird|b|$~4P%3!% zz-*8^+IN$eZD1`?58&EBbQjpUQY>}@#t{RsnKah61ioFanE=x^uD#EQm)luW*5awb zpy+8=AmG=M0sLB3l>WC_PvN=ZB7q3{70f?wrASW=YcdNgo`r=jYg`udYir{LsBrh# zWc)fl{B*B&ni3mv&Am+0QjTc{V)^!phIhMeoNvj=N!3fq%enZkveJ%ZLwxW6>4 zMPd{Ek_A8|%m|WiEdG20#GyF5za)_f7e757M!FA^G|mR!66UTNmjY8*ZR{em`)6QJ zbKWaYi({IO=Qf*m$zRLX%Ni2U1GffWh_kQ;8b$UeSAey{?&{#n{nVI1W=s>~f{4u! zXX~qV+Jx6v`6d9Jx&8{R;BL9w$vwO7TMO-RpA$YSASPHF;K;R?1vGY@o*FwWZ@kWc zk3XWncxlqxEgg&fAPd^Ogaj(hfK0dQ{Y>u7&A8&{r>|(wY{Md>hf4*@i`-5n*jSrZ zKdxp`!M^AvBtA~`%H08V(>xcH&_w(vo@3?2oMj<6J0f}WqU?`V zXwOWrug$YjcD$bs=$IaE2GvDX^?bFt4v?FoBVPvzIA`TR`>}c2+6xQ8JAy7wMWAu9 zD(0Yr12K>(7dc^M2f>8^#!=W)Y8p(@lPFYX^D*g?xZ z7{w&;?tp=cjkmFU@PwH5<0U9dN)0Y0vz#{>1c<=k;NS+sG)PAOJ*|-A>j4L&7Rg9w8&7Ja1R|)N$Kx}nQ`mh*S(U?3 zaAtGMox|-pH&8vQ4eu}IG!n#xfRIAQvgdu+QYcp3=h3f#+?z0rb%xTC6(faO8_+9;^&UpJA-2*OPLmW z2lIu4_~a=NtXFr^0obdU;uWdV*ll5>6l#{&I5v7seKl|6^=Ki9nHy6qPO48V<5*w=-8%u8iJCzOG zhuRBfUsr8VdME}ctme`30UMwR`}NQC^D2n#XnRzrR$TIIa8{ofYiBVmKL2{sTVM}n zgXpY5dDfLf6q_|;4MNFOY`O+;zAioiby6io$6iR)jbEWY4W zZ2ECaBBJ^aY1MF5dHFY4;(uM51%R%Fnhz#i!j*w&H6I^eR`JV!Xmrt5-VVi+ej&kT zzK>!1kpd4#`vxi$)u~?p{Ot5zC}BRP3l8EP+#?0Pp8?r??M?vD1~UK}ZU=wOZ*X!mWSbt}aLeb`z#CvN?&)@&JFavSry!dc?NF zFbxvB?qo520KC@JeY@)N?~{J1z_xW={~6D37yo0{@#mF^B$65|Iu433<=a1Raa_6F z`{BZJ++a|o+Q7=CVYe3r1qHps>tJD(*vHKjjbMjk;X`a<*ED1L1KX#xx=%vZ!53cs#_=^AX zYX9XA|2sGQ?=SxUpW=Uhwg1yQ`EOk9fAEI?%d7pDKm5P-@!ve7dxMQ96U?zY>f-aJ zIs9txfBpi2JbvDbcd;jNKa(b8Z2Euy`2Su41oD5&PB=VYn zfRnD~&n5nBL0*Ei|Bt;l|A+eh;)f*?6_vCgv>>}^>`U6b!%&vN*s~jB?6OBmB^1Us z)?}Gs24fxDh*I_}gRzb53?}=|{i4s~d*6S<{rLI;^Mi-i>$=W4&*yobbFM3K{MpId zCm#HFn*aRElOgx{-i)93D}0)Fid`Xxsp#8?rS*ic?0PH?K}lWd2;R_EdFr#0TF|qY zR>ymlh8(FKAxmX#FRlV<8t`TLp6_22KmPQJKa}oY6hHnLf12L%_?P2vMmJCYi{i(h z{_h|D-^Ka=v*lbDJlm*jVG{p?<(RoxUOaKkYb@2kY_OS|r|Esua-U=s&-8BYZ_QX+ zTMyRwmf&hPpa#MmsV~RhD@-R^ms&NRBH%=Ry2br>d%RFONo#N4^yG_Bnza*CP+j-oGgR&0||PRE&_oFP;R!7QUPb{ z`Zr7w_<&2mfiF>ke{OB`#g4@T{0^E=+E7SkarIdmz7}34P&$IQ)#M&aUQML5d+*yN zRYjr4yoHNW7iC0y_fx9G+U-0#5+y=ua=F zT9D9k=Ok^FZ5ylwQH3?WotA@%0cWIW=i1lsJg`1qg3Jg1mH=*9Ueu@Gn=I)i{56%u z*xp)PT1x676Cr23kAW~TF|oX^pHHgAIJTn+b?Cnvu5ZdxSLCz|_&R^~VNE7_()T6> z{TZ8k@;~Qldk|7qwgXJvYV6uMvF5c{`@g{tyj9Pg_;a} zJ&Zo@?df@s6$V~k{QK8604j{!z;vWKy{Eus3EAcVHAADM3&WU(dG$+CM+)! z9ZRavSZcAhy#o2QxD;JyAtJ)cZ_mOl7VGy!Q-L)QeBPPR#UY{q)-o6P*q3SF=V%r` zBXaLspI z%J3?`ou`s;Tt`OWy7g~6X0LjrIw~4?$?J*Ou=jQJ4f^b84b7=7u6fsMW`S31ia5i| zqEh5);AQOPvGT?Qb8@~+%aXZ3wY@F(utII?l&B&U(m-mn!j6v_zSs9OdurUZF6=1m zlN(mnb9iv0TBOTMy&s_-td1s_d2rw0^@;brm#e%bunP*Q$t@y(no`ddI4@)HUEuWS z=7+4+-Lja_Mbu=p%lr6Lmhw@IrE_l0$fh=g-=AfCCXP}Sm4p6|m34?}QwJ{qGgd7h zb)}R!;=g&(0(Mp;7(tZ_F^AUENvNIonq;3v7Xw% zeKIo=@+Y~uR~t58lhcMMD2f%7aR{(4+ZH_1-L;t0JvUiUTUV-8?O4J(+&dZV$F^6L zc<3w_IG-f5{~jm#E^WyCVZ3h?>OA4OfsvTd)hhMTzcRjxGG%q6?h&EOnX}`gS~>@i zFppA(X?bxXX>?HkcKA1|z;menp@2llbQ2&Hp=#+z&~z{TxL|t5DeZO>GJQGY18;sD z<+}lO8NSH)*_ZU_9%#QzyC)dh7m@J90S^AQYydK6J7h-Kp?9{K!44D zQG8WG&uTFy-BEF9c<`k+R+;+4S(ZQF=l;@Qtj%UY^5s4rF_ENn=dhGG4zcC_4V!23 zg|Au_-cc+^seMW^8*6;qDjij^U@U%v<)eLIHxm{!De1TPxKK5z5Jj4$V)jN%E?x2w z;U4|c6mMbzFQ^#4v|lH)>V<;z<#5U?tb<=Vn|n+vur;Pk&J~)i`pME5r3pamsb@Q= zzqF6MuT*I7gn(;j}^H{Vd6==x7OFjJeTdobrtvl)2iPN~2nPk88yJU^B zAor8?3!4isb2t+pejD%xm5&y<0#|H`RS4&COt=o{OEBrFdAe>58Fku~Z+=0`^vRCC zv<}!w>I|5E)h`XY;_LU$S$lQ6rmDKS%zJV09Fw%ngL%B!DpA6V-JD(P`i$rQ*- zv!gg=^pc?-_)&i|nW|;N-j_U8KI9T%lD{-q1~Zq2vt61Lk4!4RAb8jK8ms{-!s;}U zRQ^7tU~f`usE)(kkXsPAR(^3Vp+_}3soX73k)ug$Ov}X5eEOPuFE4?4grKJa+iN+FyEYx^$P zA=ya6oQs;IReMDn!G-u371cy5mL2iz38cD8)qs#c^*lc1(oc{>%~t){1#}RIK%mj> zM?(52JxZnzcq2Mi{$psgjG9*H@pfWe48hs^p(Yh+HF^NXyM2N^csCcaSSJln&@$p; z%70(Uk597Qt+yZK5fMQmW9F2t;Ij(LUQ4Py@sf;*a~$QH71;TSq(P(3tr(d@c|h#; zAvhvlhD;`T)4Yt+c*9%#2aVVe?@bJ4%SUjQ0l5vCSSOdX>`1RXVBx`uHG==K3N}tQ zR-Tijt*=_C6iMs(Qv*e!bEi2`l9jo+_M+*c>J+nPmTcO6~80S3VWB5 zR6f1?{{8zc1-oR&Y6L$yz{T1`VIZlzxu76qVsfn@rl&#yS3d&FflHBDVBiQ_yFq%* zU!{iW9JM~Txyd;@a%G)Llg%=HX!-VskbI!O4)WN|^s#BAcGl)v*CLC$xA4`W%%(n* z@n>X8Kvt;JbLq~9tR`yi!=qK8E5-+ZfCbKo-^tl|sRA$9gj>PmO~tPm@}l^B_jlG6 z_Sd9)hlV`r`N(g63*49Kk8QTGb4Gwa9cAvNs>k~vTE!&Q<4xi7amrZ)z`o3Pb-FUr zK3kUz%URU-TI_Y7>?ke!!Yl9g*GaIu4HzsjLTGy^Xu^2#+mad@eWgL9juz{jQS{6` zHe)rBz1qTBuUmt!9u37gJ^l7unZ+9sOWeP_eQRhEUi8DKW1X1FVa1KT&}94UjGJ)O_DJ@H*(#yJTm9?53SWtk$@fQl%dj+ z-z$~1T>>sv@$&LQKf5yv2!B0*=T7jE8QSzhN*t}>xSrDg4@lPs9*6BH%Uzzcqq0YD z(8qmVhNCR!9G)4r2@g|3&3QOS$0e0VIYu})Fs`a9-cY1S%U5{cU&2h-cu6Ga8Of7b zm+XykI}M!NK2Q zJFVdf|KKyfoUk7Uh^b6@*wb$t;1ytGx56W~VZ>w-K`>Usa$Dd?O$rWXh~wzy!?SY4 z<93b_S^OB03z=hc>8Hq{Hqz{b>S{&S&xVEO*sN$31)NqI=7CIWuafOC{~G)6(UJH3 zzH#LI!j{SaI(h#BM*dcV0G!6b{0tV?lFBs&3L@!G6;)22Hhyyvxzj+rH_jr>qbH3rm9|y9P56g3Y)L^?mZ@q1~4k57qGJq zoJDT<-G8 zBQ{lk^R5+^*-LdTlWi`|e~HXKyJX@86OC*!(bTBKLYkMgh8(T1j&7z#0zP9e(FiZ4 z){VNP@)0JvJDg@JNls?DLqICz#bHoEN7rUmZU141fRxYUUZZQ;o1SHHK{_7i~Bg6AmE$t=HHT zOxy&cxsTh`J3Tle(?-(MbZTV+zy4lp_EfNgCa^QOrE z(hFH}{)R*UC)0|zZ9Q&FJBsVuld%)`{dSZl(S@6EYp^BYQbqSJ9A#ai7d`5Wpje(! z)#R36?}x4njyv&I|Gt&f_si{5^>c4T{!ZWgJhH9Eq(^}Kz5_ORTkv|bcC-7&IT$~^ z36LyU?p73+0|&xd_&M?5pT3s%Uwp>MvJYH9FQ>FI@22S#?3_R^&F1U;ti5vOrH2w5 znRn>AS&n>96nPSWF^mm6kE~#R%t>0&!WGUR*%HZ)Kk}XI0=UE^S<5a zTQ(!-3i}H9Py&4d{FZ-Q>D=1&RKOmUgCzXPt)6RL>b#?Y5WqQ?E%ByRGckOpqsw65sG4?-cU=9X=Wo$)O-@_|+|K_W z1h!E;DdOC_Sz5u$CGg)U&h-&7Q#tf;(NKHF@C$Xl?VCm< zTD}HMG7*oor!$!=;Fiws$D34$?F<_G;A3)?pP)<9#PeZEDFMU>(z1z`fEX&;URyy( zZ3V$&*}D#Ock1@Bb`LdtH1nfkITm3AK^3jh5!t*8i%h46fE!*%F!d1|%Wb|B8D+}e zIiY-GR!nqsv-gkba>RFrdV;CThSLX0AiD<5#HG&1wB3Ewlja-4Y{||RgaKX#^`H<} zBzH5|^I0TS{P}8B{v@JKErj_^d&ncAP^W%Iukh-bcVL5eG!fA&WfqT=flE8Ng2V&Y z;rJLKLUYOjPKBVZ`iPucr|Z4>0aEEKuPY#-n1s|VjRyk%b%B(P$5#_aTUMx#(Z&h3 z3Z+_y_fpATn9Ea?z*;BbZgIniPZP3E&C{Gx8ZWc@rgl~#bb9hf!{Zw3_#}1r`o7*0 zgVTT?XVm`BorlUvBO_uz-Flsug2%+}sV#0THOqvSIP#<8QSqc|sCVh@D0yoNEQZs7 zk(9h==F?KWc?u+BhMitljU2jA9;LstlDu9?ZxkXM?SJ>$c|#GWClQ3&b!-KC4^;>z z=Hj~@mBiqYKKUdeXUTBF9m5Q9G#86u~9^jP4+cV)xl0KZtmU|q)5`q zBdVY_-~p_M(e0d-3L-IhgJrDV@Y(QnLz;GccgK42=HaOROmcR$#rsG$;QTp>psUysduEt|VJ2haX`PizjzflI- z=3hO2A^a*q%;a)<$FEh6kF*$$dsoH^X|Wkqj^q(Xw11csOb61mCwlghKG;BuU*#R< zcY=k8(10H*xndtumQTF0A7omGPDG>T6PTp@D=!<~l5GWokqczXhY~Fkvgr9FO8yhN zncV22(a{tx9Jn)qlv`ZJy9eSuly|wuZu6a@%gExsV*^sfaZLH2GhW9xKp#gc79xFS zKr1dp;Xy;rj~h2Iy8&Bm3<>7LF7hq}C5|O=Kg9_LCVnenPr)nfd3L*B>&kRX4{g`k zezg?pCq@TN8})3!pfl&dKQGC$({6>iAq%s|LPpbUs=QMB20l`MzNyclA6QjN%LRh% z^*2Z4-|}9lH-4Tde zk=V{?@H4Q2Kfv^7tunEI^S}SWV$6Jt_e=`oWIdw;dN_+Aq#BWTff7};ANvv|GnkMZq~T%m2JhITvTbNUb^D=t)+v7*dTZ5;;rPJQ6gL2;BeKf0i|Ru}5= zpN+2yQw@gjBh#yIoB~YPC)|`14kn%8i;|tNn>rb}J+_{%9cPV|{J&-h-dcWC6dp7@xMhqe_{R3sU zbGPFK>q~))_>s8b1`WbbB_nb!QQNyygG?T6em0PN@M`%hBc13uCQJqh8;ioa_OHw@ zGZAVQD}Xg8t+-S__% zV3pAvlR4d3zJ5{ZMU=7sK~^?<7}PC)PI5?jH4u_d|MJC)<4R&il1LpRVfBO#%CCE;A_FTK-M@7@Wfwl9C1X`%&x zErP~afD9TVw@2R0iSf6eSaMi4Kw5C>1@6Ly4>!JSjTNP)Br7WcJz&QCI){4vyel>Y zs!jrO(Xs5O-3Bm_em874@b03I+Mb#)(L72KZq)AJFN-%Do#y%ipOct8H-dEy*tFqT z3hcM0C-ONgU0*7H+-j??q5ZZ*px3Lr8%Sc;v5(i1U8v{ za?4Cr#?v3fi-`1R{Z8{0Y+@k(c=7pK{ZTl0`!5`1_smst%AMU*K6_30T~J@jRb2%+ zUDm2H)?Vm#+H8KBvMLCk?KMtlQ93|elF@QCLAF?9jlH@aH#`A<>oYMREaa~&RcY6u zg=Lt8si1cM4cC&)deNR>6>(6|&b2xFbmT>JrTakS$rsh2laffti~YG4m3>}764&sq zll8N#hB9TMxlhq?f1LZ{QX&KZq|6h6Uys!gHFQ>(&j{hvO_miTY5+0c*0 zJ&=~}XQ=XqadC?iFvE?`7yi7xAtujBIqPIlvLhYL$tx?{@2`#L1*^da#2W_SQ;LuSkD=1RRnO-zR6Xu*4 zeav#3Him8!$rwo)rtj@1*4{cA%Xhx2d>(OfCJ<#N!$dQf8l-7@Kk!!I7ySHrs6+$3 zYF^O$x+7MX3^8(M^%PviOD8!Xl)(4T(y51{f0I&VT2|Vb;@TF5?F@FqiqnWbmDN<2 zuyu_!YxYSQlOb`vk?L6k0wli-uS}4O<^3=So8X3*?4G)G`PA124KkJYYY_rmb1vF` zCV9~^V0#zi{{9-LPVRKt^Q$df zBiB>Ay%8=2m5*(P)8wHkQ&eQoWXYyVM3S;;q41r^U%aC?4{?-y@3|{ei=%_k&gsM| z$|pp_3+dM{RY?8QV-B9=3}=8gI7Kb$uCEqS6f1q$@xxz-ZJsRE7vrPlO~|X}!&U9m z1DM6{22I*7Nez!eUtOgeY+n0aW*jlPLX9zuonN2Dj`o;`IG2L|3O>;%?hLIQl|EK^ zFX@YPZDe!8?L%LFSA+Ehz8oWZ7|Eo2!&Gp}+iLtJVuL=r)`NnDavBhdf@6C#-mmY@ zf*A)qUl)iFsb}4D4P&5so1v~1fj+5Uek$|_*6*Lg1Rqg*wqt7lV(B9R#}d}C;PDC^ zrsH-e%^>16sBz(smU)zMd|`riz*i|9->E<%8$F}lfots-*MI~k!{9=LrvWphWz!c# zXxfa{v@6YetNm?*gCj)KDVZEmVUAvjR*~61)uJIVm4nBhsnt*!XVggds#~yy*$8^* zVqk*-4`EH!r|A-hhE@x1z_^!^wJ&fOPX|_;>rT8)S04)HnuOPxTR9r3)rwNuVr3VR zTwUG@&K)a0m;JqQ%s#2jICiHpGx35?JK#_LF$;BGEQT(hE*gg|JCEp#oE@!5?oWoo z+d9p3+f*EK><@n)mAtM;9*2bsNi1V&X=%nM$0Sd4#J_E$lY#VwCdX$CMmb9p`$b1Y zkS2#2eb#?KU!ew8UZos#yP11~m3#g!`v1cMUy?4Y=}S_h9It=a$sp6r;g6TWXY&st zgY}ljeSTyXO$kg^qIX^FJ2ePg9r_#1g&*t8Z&Vj)Y1lwF!=GKP|LiP03^FM1+I1Ic ziyX~@fqYF|KE$i$xlKrLd_4O^74=SCe0bAbNnTO5%GtrL9d+ScCUHv*=W8u{0_#}q z%sNwPcPda#YSq0z?Pfj#Te|bLdArJg5&k{I#i5*6PueHfU`uz%_l@*!2AOB$=+)z| z{vXQ+3S|k^TL-{iBMZ)Pe&IjV@Y>vw3Ff7@8qNdLb#5>${rsK%P1xlizrm2~H0# ze0UBuYE$Vyk>)C!_wfm$GqO@c_JB{P2X)qcC|g+8mlCj5yLtYrzV^HsNNia7#uEL7 zC$x3D(SU$!B}P~{2M0l}a^}SvgNAyikcd2?vr(EE;DtiRjW$M)a_C=@Fa{+|^*K9v zQk;QmXJ$9-o|cPL=j(ikZ>ukEN!g64?YJQGasJG3Lr=* z9|hL58g3waVp+)vua(%9*D76d2b44YSH=KQ8$kOc`#A>r-y=a|d8)SFan`i3Y68#3 zHYY{qEP5IS=X1UzH`1|YyAECv05-mG&rfJ6(Q;w4_KXiYtXPY*4B$$KeGK@G1FR?5$YeGFJUKb!jNv1IG z$+g`ky~}d$|5(B9o9dkGeE?>O8%!+T!{Wi7;riDN$3T<*>$3}L`CbPf`$4S~xd5*D zX73hnkztTnLVLI!B>m<(F243ajm00LIaknN196YRk_kDrD`!z}&}2fX>64+myL4tF zEa7nJ_w<16YtsFnNVgOs@~ZgFVr<5s%dq*NZuCMONP{~#etawoVqhukpFbg0tajC~ z36AvHC1EVwifcwtQzQ|$v5TEmDJ6mQFDQCOVra+s;_H~v?cK_l_BRbtv2h?$+C2p? zLvFFnHy+5K-ZK+~M(=)n^L*KyPxPCs4*o#9K%|{skk?JWV258$`cpb*(Lw7KQ;U^m zfBt$iK15CQwfJ{7rKY4SDi6aW;#(oq*P=@{)wb+?I3*~A#u*ky!uO@#=7>l2araOX zvsQC2X_rA|vgi_1BeL%dGBNkmV%Zdd7qxu)Z+jQ6OZ8{dUzIL`YAOgSLiJ~dR=Mog zpYZGWe#Bqdi=6~<=r?_Z%DddU9xg#*CIxNY0wJm&w1fLwV2_CT1_HsVhE^~aw=z+k zsoJ2PdmfR9TGJo2TGcdVXTUAw9h}Md)uWJ3&`96+B=4WZ>zQFOgvzpe(W0(K3q9`g zlGjhwVDt-HS>{(x$>s;O`%EHg4Ze+CXW=Zn7CL-C==Zysg#5e4*<9k@(&Mw>+jmJW zWO$hl5Y4stT_{j8kgyI^2>5k2FZ4VoM+IL_Zspg-X2|*xlQAvXKcu2&_s{)|;eb~^ zL`B{M1ZZ8gBX;wfRna!~hU-=L)0`e4-%owu7MVZlRy4|Vl!~6)*RDLFJi{qAgkI5l zyxb+6*{WGsqy}{}M4}T`+Hl=Nfj5)a42Q{ae6Bn)kTFl$lI4&HN+{6Rh1}#9OiJ)? zc!*S4SK`+Rii`WNV%jE|PH-nRm6}#iF!7mjBN)559c^RYnKMqjd!tpBcmDJ}<+`(3 z6j_&TY>huIff(3hQwbAiuf3A!G?J5)I%K-H(ejoV0c^aBNI_XjZ8cNkCPR-^1|qd| z`jN46{?}2EZn=(?a8*HUS`914J%nlPvbDK?Qq91T1SER>pQiQeO`YA-+#WYB2a5e) zPF8YBe%b93e0w)Z0xkzed!*;@Sp@&BEAg!hoqy9XUs-b$e-83`6R3`%}n5e^z zdXlU7n<+3StQtd_gcF{Q_L)qM_{Z+G2R}2q7TaIY#6igHcMc;+*QyMO4TInbdW^EF#VEP$A>JW!v3;Uh^{5{Nq;`JuiI{;Xhvwjt$Mz~0=|`)lPoBPVo+j;INq%-!Y>Gm zwg5MU2UF)N%Syc{fw%aY{xzS?OmN{D6q%qlpl=y!+8JSjtxz|>u~$S! zi+Hp%3ATmbsWQ}nX@4dK$CYlpspQ`sE%8XLOqSJ3jBiCl&T}IQ^I90=&#oqStSwlC z5bb-oG5W$nr$cAq->m`xYU)Y%kF40Se!W1Kqk`Pv` zf?t!jQ*kfPm?Z1y?cA7YHLlC_avf?r6B&e1kI*&4rhmR50sd1ekqq7@y`SCg`56DU zV9QrltZwb(cGeJ(b*f)V{M{cgcH{Io)gc;Vn!o<%RKT!Z__9sB^6m&I!F!mdyM^5A=J4ECB;S# zDjgiyFuIj}m4k>!T4 z$}?j@8&5dA*V_i}HtHWHU*K2tUU(p>m!8!mww zls#-tIUsD^sfHn&8N?);?>@4*L5O4~Cl#b<`6&6wZGXzW8o!Qs>u=_7t-oC^^L^hibAG z-wJRSm$mOcUuN1d6JKqqwpjV65J1c&+p@&IhrFZaKsn~6>)tpJ&W=gC=}1_?RX+&NZZn}j&tKcAqfeGYR&A% z8T%GUMf*S9Q+p>@DHi?It{lVhy#%sv=7Zir6}D9G3vW-n#{MmW^n7Fb{=tNSiNE9{ zdb?Euv)3x|W6|BjBRs1I-Tz{(wt9!bHhuZ+?AlB6wykbXKFDJIKc)LB%ANqR;+m3c ztKcNbwH5xq>b2f^XAsx+W0QV@-eHh_%t$ zrP5hXq`py?Q?;{>KhKa*7_+_9aB4w!8FbZSXw3XXeF~t=zI-W%V>qgX+mD^Tc~m!+ z{)VuyIBYxNI?$q`m2b*ur8Iv*P72(?(=j<=t8m0vI$yppRp#s!W)Wd$DK{-_TI|OV z<`h7HggOa=7G~B1X!F!d52TRZvLnfQtI>h%^TN&JB?=?EFI5-lt#C{5b6hITVC90u zvz>z6M;4npZ-M-#<(G`KQ7i$HG0>6IVCn%CY2v8BBy6Uq=0jSic4!js`_}a<6*;j^ zJ??~S%A)O%ALZz!bB#ZOc}6T+ZQ1{Bp1ZS07`RA7CDc4Nyj+cV-4$`)BSm2C zn8AvNq0A1_wYoG;N6V~&gZ1v@iL6z74uOkUnb9Si^EI7%LMeNpu2<-w9Q8+S!)Gl4 zBlkRY9L8m?JUTqn+SqkP-;8dxgtlO%4iV;(C}(~bt!R?;lju1ZA?8;G!supY7L}Sr zQVt(Q4oMhJL?;LrBupB@O2X4il6XGsq%}A!!wk0BZ(%4NuUl027e;4vzE0Um;d>bQ zJAGSS>FpxDjW^Y{#_LskpT(S9s&pf{B#^{ibF|Xsk-b?2YRC%e zfI7MT=PXSmLPgQgKfF38wH$?H3GCj{%U&Yk{S8G-2{)h?@?lGpd!~A15&yTjbR`}q z#zG{KM5G4)|IGN9Z9BlQJikY0U7BYyxLjw!XWma-?(h}D$~m_csF)|^)+yjvWIUYP z&zgYCiEA+aZ6Axm9fX9g^=jk_hJCrsgq=q|=s;~K-6T`Tl$cRl8wiG@Zc=@N^->*LNU>mud zWK!lW>_Jy-8b|B5A!&APhD@;jsDUu{yR-KtbT;#rPAKl zEs?3RN$a`7tKW%w4%5uL9E=mUSWeNN-SP{P4e}_i8GlCgx~|p1vr$_aS#r6mq2*1X z8_c#EI8Q4`d0{nFQu>`?>h1NysHMJF&g@He{v63Nz0*akh!cfVhHkGCh- zCMJl~Jv)kqrJ_p~Oz@)n8Ih^9t^aI!4*T69Jhv1_`1w7s@>!SBlB^&Rzon#&rV)3k zF8sU$zjkn_duI@}bS5Ap0~$a7csr}Qw{qzsh*o)={z)7BC~Fyh_@}mE2X=y3SgVV|xxeY^h;Dg@~gSyQ+xrKAosoCj%jzmbu`uu^1&Xw`E3+sYV zxF>jQAwfW&5)|G-JkW)eV`Agj#UR4Dz3Da2=E9X8FTL%_)-U&Z{=kaceOD=0RNcFr z?{UOP^^^D39S+LjTwT<>i?!Y^1pSHh9WLJ=T}g%FSIm}lEV5lk9I=1L8`(JpA(~a?MV!rIl^w9hLjJmEc6{mN+6$*6!9=`)7EXvmML3?OZrjJy!dx|8n zk4Yx(hSYTb=UGCH0T5y6p1V}Z0>&T=qy6?pHEE0DgWgI#GiA4eAAU3}uCUtMFSI?D z`^&ie#-P9VOOFAh>=iYC)b^D_4 z-JKY?z)sJ`%G!jipN2)ifpY@xo7_4E6b7)4m9;wrM-sSUQ+tD0qj@lm(%)~k*C#B` z=<-)Zrm8UaZcZYbpcc`Kkp0y|KB@@f`A%XFQfc$CM*5xuI$y`zkT`k%v~@_*$%XfE z3y;Ki{Ono)t;+J|d4t)-h@?t*YscmtpHWR@(07jszJVp} zoiu;VncawlC)hbLSel=-eh9$ntJn6^O*4KbyXMj^PW0#4*wm{{c&IG@he&#c@_mw3 z`TEFoKfx%4NL2DUe(k7VSeoE?b0}5uet4!|}_5PKmt>&xS`O4^ZE} z7k!`v0R_PA&aLun2zPdyuY}%wO+rgYXVBkEa(BGfc4na}yWy%@bf(vmQ`lMQ>eUt^ zl6;rRqkVH9QOWlKtkkCi7WRLMfXruLT*=odXVAwYgjph@nk~3~LUxMcA1k1;M-OW9 zzH{gD`m0cV_VFBP4R0~SCC9>8|CKCT+iII6OA(G#yD$7!-p>W?Gk9h(c3Z}F`>$;t z3=XFgOE`Ly<9j3BOYe=-_LmnirYmkBmul0|@6Xm&2Tz))P8U1%8Bn~d=PiOtE>e68 zQ}(2$%vXZ=qk|vi$28eJ;o;%?i8L^hp{i|fHC~-2bg22#)qh*+PP}l7Kt5?%5)4f4 zjPo50FaG1T8DP1Rj@U^5`yzSTrSv}=Z#cA2%AaN`uQA?mB*vDIDsWNlUY8)4ox!eKi#E zZ63bmEh~I}7I_J_oLML7T%WZu^>uHPeLO<%uluDQ(eaFj|1uFNy>(c;r^5B{dg*qE z^kUTO&t@zEI_1r;u3++dVHjT;&EQ~TSAVy$^HMzPm+^l0NgEHmN3DkHjzru+?3ETX zFVoT)d1R2d_haYMx{VWw}>hHVsBC1Q1hZ179?~>*xN6h_`)A zW49VOC2<$%i~CRxB8P^aY@>6z$0_ZN0mAV8-9NwBfgfCw-w>J4-n|~X7M8i!y)@fv zl3{Wl=s-gcvZ>~b>!`|H+v|vB#+UeJ_owIVQG(5v>fK`D3`5G1P9rKJpCRLkOzN#k zEyS_ZF3iRxtVdAg+vFH@!4C}bMs)pF>`b_hO<%ZWkkdWPFKH| z`@R&kZSqi2Zd+Ii?h+mIg}STr$2}QVjbP9>{rK@aW0W%?BL+Qc!n-q zEyMD~vlUeMQgkwA{9Eo1P@o@#R#E5*T#T`f z56MC*Q3Dun0Sem!6=Si(4{FN#nQe~h_hZZFAmwl79fb8a6Sl5vD9;wRs7yp^ILoDO z{2oZ3YPri%zvg|4PIO=?3M=V9c2v!!^JI+@2X?shgx>a0Pmi>JSUS2zEV@MsS+BtG zP^GzTHUb7c)uZ!ORlc@NQS?`%6EJ_r*?x^|Ns?m7*&Aa;cd;uwbqO|8zAe_N7F+mzI|63mo;~4`$JX?P%fPB@%|>|2nk$`>+H`;*Q4- zJMu7pvw6{icf?`3adDNeWyv@jN8CK|;IAo{ob(=w-*upVr;#Z2DY=J)QuMF_dAUF#aP{=h_iB^kFn`mwF zLsH);?HN{AcVbcJ+4Sd5!=<^yJN9Hh=tJI+PQm^k= zm*qYH4V%B8#5CJ*GlYkGHs$jBZ@*$G+~&;|-^XBxwf`Obg&g&?+nG7_ZYUCwts=Dt zXF1F_4aoa26OTWxzo`_4@)5*#TIl=d$hv)V5N_*j=!%i)9~k}4F2|`Z+i?AZW>F=hn}cpXnJ%_=Z#;%o?&H&uyk`<-@I*#XGgYVSB-c#{9A>4>Y=0 zw$H1a#-9lk-Xn!|Thy71mJflJ)9mx=THDAdYuGHG-*8j7e$Avc#&kz@-meK2=Qpfr ziy{}XGQkqoN(B8ZimDSHvz4?PJ)x_A0C%>rt>S=|zB-Z?JdYzMyn%s8c9vlcz0%R^ zrHGeioST&^Jw=$-5+;?U&#F*gQ=VCkQH;hHaW=t^pF_+?NWV>(^{$M(&oJ z1Ev@j!I|zG)=dc}vJ~#sq-1quxcf7!7>c$&Ph5=Dp80!V3H{~qmxoUBF!i~Rfn5DG zzkV6i;5@@J6L3ux-S4`8*^=$gHZM|tf5qt&l9v&FKyB0{`MKhz$CZLg@KNH zviwPxO0$-krPda8w+6r}3-enfnQIKH zOFuM}7mP9cdmh4vV<(+hY44W2CBwZqgbU&gYPVTPqq}FbI|E{XHskP%K-k*Yk^gUK z+1XG#6S2`^zRG=VL|Dw?it^~wzAHdl;{EswT&o<`2aiPWjTBplD|PA#Kdv}}Bk$uG zv)=-My#{QroHV5KZ_oA!Z*;W6(S)2K9Qv)g*gJ^Ub{6ju?DVv%aNb8DZmy3(h9B$F zK5?Y#gh=q~;!7CGVMu&ceDl09?t48m-q86|_4I9H!mLlTvu9nK%85MEv{f;`NRL;u1OvSC33^eIV%n7zXroIN~o2nAZyq28PGvrn7C&nO_L z2Jowa*o_ovrD>M^Suea;kl4`@UbgEO>jkERxEWA|+rMuf@ss0TeutCObjbimkd$=& zr-35j4LZ4v-V<6b*Y0uXe*lIezBHXv)tl(Ih_ev+iHw-$dtn(w1AVoVgr8b6rSC-L z7B)jFVbyrklG|D9*HX1{dadAA<*CmaX?qUY9Rc_S)AYEO$JCN@LoO!e3!|VG;;gcU z>N1CL@B~G_c4L<%Yo

PqWng_4^wf#MKj|;C=q7v|XUxe)eYFzNcA>2|U!D=#J1QEO6mi;_3SQusH8M($!I1 z(~Nn3@1{xtK>8n|rPD8t^ebh(NQj$FGQWl}_z4{9#aHc<`QgV4Zib_5?q4f;DKq=t z^y)UCPM%uP$kHgKs>$}GRX+b*F`x_~nI-YNY(VmZ2hCe#I`QP7h6BaE-SKmYcjEY=Q$qu}|4E4tu z(!Z(1SF9HjyZgp1cNvrfdd{H$>BnGV9+AH>5#1^h-2&^&hGsYRE!j*J1%yp~!Bm)E z6El2jv1`bW_cflY(Payc?+#vhK%nyUvVgDfpD(xJm)1z%G2*9eNZaCeEDXdCd`Lcs z2$8@UPaUd(fy+Ue6D=r4%3k#$L3P(&K3}F>=Z7@wijcGLtB5m3W&l_0-mWXu$iDb5 zJN~zxo($~Ic2<6db8OXJ_Id$7-@;4I>Apg_P3yBj8}mfuJ5JC!p|Ku?xamh`$yXs0 z)x7%4G0`HQn_HVVg*Rtt@%}B=Ha_cO4_-PocdXypuS~e(Hmzr{zbvSK@FSPw<5HSQ zSy>Xnl+$p#-vY8;r5Wen8xa>cNVVC-Ml78P%v97}tIO~+hODW4vjP&e&;|NaAsCXd zSOyS56^?r$?uSbf%#D%~ozVr2s>Cw$1l5<-7~;+sr-Z=AV0M{P;YExYv7cf)e&JKE z*>MlyV}*>-;>OztTXjsx=V)Es-*+^3pP1Jb{@$FFb&Bbi(~rJC{Dj~b|K5tEvNeOp z`({JZGjIt3&%9}z3$~ z8DyKb=VZ&XDMdCDiT6Iwy|tq5o#(qdrGb-w{QofZ<>64bVcR2>qNs$*R>?L)lznfd z>|w}G*|IMoyGT+YG4?gt#+rQ}OUT&M*tcTrjD0Z1eE0Bt@B9AqIF9FN_|1Lazx%qb z^E%J-Lc6xFUY%cd8=CcLw6Rtbk&=)F`IKl{Up*y51BlZ96`q>0MfTn?Gh%d;ljk1p zwOj;sdz|&8PoXsc%m|&s!{Q;8p+6#((Te6#(nK|c^!B=QxCEShdAalI+AmU+J*TaE z-!$*`KI7tEV8Wl;y}NJ#`!p>+V$lmu=0@pxn!r2WvKx{rtt*W4M-qAvh;FD0`el^I zM(zw7!+6YrGjDZxa1a(f?uhi1bBsLjBBgFTCVfNaqwLB~CQtjkqNPLbVcfHKB730t zWijCBZP{^q>-PTg^uxobf+%>+7D}srcM`+m09V!zc`c2XAnwNSIsxZ_ExyRR<4G9C zQI=15X1ot$6H8*nleZw-^>i0jFBvvF;x`_LDcXzg-v<2q()3W*Rf=G&sh+I9&7JaL zltxU!O}5C|SaUp~9eT&HcEfMmci2WXxgu+Y zG>N)wG45>$q%i?-M0S5%$jC!p;InDbT?~b;Ob{A1v~j_3-J89>21?;cwnX zwX;SGb}QbRVZ)m+98Ok5RV^?<{jmHl_>JB{V=q-BF&F`<@v%$Ix;>S}W9v!H z?FIt*pGxdq5nrzeXhK1f*Y>h+Zm-UB-kkD1E{rTu5rH~j1pQU$LGvJJR^Az*bZ0!M zZ$)6}Jdk7bJ@8p1E_LPkvk9ScU+NZPX)AH{!Yp+b zUfON!)j*5VYp2wnT$LNUQJ9b!54gr? zoyokB-nUJYJ~}DMzzQ!hpZ{Dav)%W_Hn>Q`e}PX-r!6r=~{0(IGs<2MJ~H}+?FcV+?&6{8dnuRS}UL|-QWi1Npi#te;+-| zJ17u}3zK_PHhEj66elPx&7wnw8&iFbvf9@l$v7?xds5z-*A#`LIxli(vnTst91p~F z`FmXrA`F>^Xqi2@qTF8wXM#?}Gj%tf(f}1$#Mhd`%iFcnO!+$vf$q8cO9HtE{o%Y< z*avIpPA4o~8O`75L8St`1@4LY0j)h`1`ldHv@;Y9t8owA5O|YyS8Z1x;kSDc?zdjG zD-#Lx0jLarr zyf>Q>^M)A*x%JsU-wSxU5E?;Lp9 zYu~w)=e4)YUMk4YknzJqmW~1vTVD9G{Lb)%ZiNV77O=BtoggEdUB^|-C~f>w>kUWo zhh7uc_l=)l^YwS}rv#A0z^+$H+I~To3#wpVv?|keJ>?(+T#Gq?0LFTw5vRP=WCstH z|5P&jhLhd7zNt|KdWdJ%8h4J=N{%JC266pik6|~=JlttRtGM(2I26W`4ojS)^NlNq zOY9$XgXR(G8x6u^ObJfJ__ZOrCWZ>C%HGrJQ@FhxWE81i#}(I;C^&1Pc{fY_v=$R- zzHOJx3YG=aGBCDj?KM(icDI=T#KtC*m9Xg{I87&f*=YY_RhF!_D!$=FkA*K}dA=^q zYj~NWC2UbR)=S;V*B>Z3 z&uCaKd;>Sop|y`21UIzDYRQA~cfUIZVWe;-UZ+1-*FS417uybJLWT6IC)Z)vii2nL z?1!6`T_rjKN}(ex?8)k;W#24H-((oWyzzTz={Y;aq@ADb+Mj8*1p?Zy?+V=3+IJFo zw(iptEmp2+v%~u=H|Y7Fw&yH+2g@s zomlopdic*x#GDLj#0fF4pYex-WROE82VY#Y!vW31ue)&FlCDA8Z*94{X<)M**E)kM zicgjF#hJTvYUOKxf`KFfRL-Gq8HZ4h8tP{)G|I5T%=AB>cx5Ef>JpI=m>w?1PEluQCRczORaTEA4#TE(u1iY#kIEN(A{z^i?OU51Uy8iY@hx zoYzaa_~VVr3CJw(Ych7yU3~ryMbWSVV8{M%{d18X;_m9&B}+Bbxys5OraISuLbAHE zmljdK)q`9a6UMI%x<$?F=O28U$lYpA=H)DrzUN}mt~iT$)0>XL*E3(XMd@a!)hlBf zy{7%`yW`JeDkd{pvq(nm4s|-iG!xld9LW_8_lsce+dme42OXl=$G&e=OlFPX1YW_D zsWuaxmc9BmU7r9walxVrDk`C?!})iyvy5W$&U14%qQ-ECjsgkV-l58!K9`u|D|X-Z z!Z_YyOSlm9SANy(-NiWU=ERGUp!@Yag$5tHe@kb#wX7^^50;P~uLh=Y)%e+Mxl7G? zuu7IM7nqj>V`fdfw-PV5%}_w7I-JbSRUp!YtPf|%qL2~xqr6FKC9$f&)6?@`zlF`w4r4$s*z3ZvdmCu2u zZSa0KeAS}wB<@ccRuoacp@y`t)=N8kXD;?n5IOJzPYR(zt&JKcD8Z8SZA(`z#rAyN z1@mOChVEa6?nn>=jG<9&43GR!yDfvcp19D>1SjbhJol)gLdQ_*wb5^`>(f1GMNV^x z0^5$z(MS53wwTvabhYyfs|s0t8ii%Eqq1KHwd)o3EbE_zxFp|j$F$NWg3iR%{u9+U z;L5xZlETLlMFo*AS_v(dVePvL!Xl*PsL5)@k-1%x14&l7(xaCYYuTYsKWmO<^U189 zTyqTy1yX8!w)Z+J*JIRyVc_G2GTbo(vp9%$=k?keM%OQ=I}fs`?Rq_V6n-DdJy$6N zf3r!481+m*lL)ur4*PLU9-Xhl0;lrbv)9{WV0E*^MNjP9OrDg8y=ASV*my`Xy^nL4 zoPvx4DWh7H^sFVkR=w-TeUFUws-B4Cb=tkY&BAMKQ;jF`-7`uQ3!mq1^-q596CX}@d1D$>y4+}SgqBlVyaVXr|&_0OO%uO_`gYLm zrL}iRfLCq!F?^=$f}IgXRF+l9$Sf5cO70(l<*ef4lKi~==Nlh#lY03 zhE-(xBJff3wq39g|ts@B9nm=iabVKxntQjEW6;2e}y(ZWXpmg4gRmHv+q+&TZvem#$s8 z5-S5S8q#kFEaIW7g<0--VvX0>z#FdvB^{I?4`*#aaXhDektM0^T`K}Gqb8VpwEuNx zLGhhp?Ycj1BI;lp38i!dUNj~z*#u1QvO5Hlqg~wbk^ej`{z;3X_Ji^)lW2w>y#AHQbAfj1%vqM6 zX-VabkMt}5xLk_6q{rrkW#0@x^{B?8W%jkUedoD6+=)glbf_YRlY_Y~HQrOXRbIL8 z4}kz6CLi8oQ-9O4`BlEF)6ifbCoD4NWpsVnqAYRUOU}&bVIO7vobdjOjj9X8HdTe( zChaRS$=WyfN1S$QRyn@1=7%RU^lc{6g@7lvs_6V-j`d;~u_gP5NirNAZDvI-K-zV@ z@?L39HOT9bLnL8CsfOX4!!shUL+RCbL5hnbipGrw--R0eI0-KN;2pvdi2I|Z6He}}@F zY{m3VK_X3ij7H0oRi#=`2AvaL$%9qyt?vd+ulv2w3Z3*Z4z;Q0#;w{gh%Qq5s2P=T zVV2fCXn9d-MI#?x{!SGxm|de?7=Xd|`?9`2(kRH`avj$$bA)F7JR7dHlT#R7^6&ZZ z-bDMyzitv!ui91REAXXlIk+YmcG9`3RgMJpXt~oRa)x#Zj#;fYI+T-p5c0A|W5)xh z-lTO>>OeDB}X;p}&2SC2mDlyPg?iFC9B>NYGcIzbqd?UBK@ z|2l)+^X+mOcbjQKVoQE`DIa&igos@f0hH9&P^1v_B!NyOxV&O@kSKe*K0aLvQ@eTz zV^7L24u4Z$%v5`)x_-O#(yE~8mceV9j%+~l;hX8sj#_$^PWKa>Wt0DU9-re#2_0BT zGg`;&A`K0}a>Gz&-^>vbG5lJMC@+s1pYN0uy9KRX*>{W5C(YIeQ|Zvd`AC5FXRse+ zDavf@DV|Hb+|&Fi_Z<`Lf~Z}-PD*NLgOg(7;Tr}4?`Z3E{S3udVRSm6xviCv;wvAz zGRFC|*-~V0t?d@>Z#;@2%IGW*Af&`b`-iQ!8?bMVEXjPPpDPr} zZgRlC4^Y%$JT%7WvW~&X9-H~$Ob}Xj_ObI|k_8(dKl{+UdJUf3%mUl z!mxy~1v-YQyrnb_9oHA$Dh${3#GVFiVM@Ra(14Ge{niFDd zL|lpeiBdOvzRt;#OBy4HmsRTqMmEsSc%;>5efHqKF6x;CiKfhdmCy8J(bI2|e`J}w zc!Fj3eS}T%RtzzaEeLy>xOWSiLS&SX$))o%FN*x))fu-)49{h--LGqvJ=E}+t`V8L zUO%j5H=49Dc_3KTA;zNX_gNhQX|-1ILrp`D~C4G{h2} zo%i)k5&6G2($fi1Gv^r~ju!|feWF}R{kF{VntM{>;ygW@QHmMQjmg{b;i%6$?$&Fd zLrFcfF9=oGFiLy%X}HG5I~Ob) z;lglxJ5o-CWhNwt@ zAA;s^U9CJE3EygfBGNlNT}9fu`2L!T`0YqwddJAgc+myYRr-5rWksf;u~gmEwU(htlBQCM=?!o& zM7ZN|B8PFP7%>Z|5;3suWnZ$TrHL%zb1K!} zhys_?D9<6GuB2z`eUacH7-|@rNRKSs6*E&DiPdzyX;Ka618yOs_d#$6SE$0?d|9e zY#s2u^lh=6VexstJWWJ4&(CRxdTB3z)21Xv%?g7PGRwul7&U+s7v!XKS>nau@f zPo4I=D?!tcCC3cweCrodkul#mH=}e~m27;*{ zpyy`7>1>u^4v6}F?cu5b=WvgZyWx8<@a8{VXuiOuS3ZVm%f$zZ{Tg)x^mtkQvc7zc z4Bin%4}O{ysIhr$S^7bgVU7M_aHb+V#Q!Q_2mSc*qmo=yLRLbK zUa+p%DX}C~_9>S7gMVKxWi|;oogq11L9>tK{UfC0E=DJO*K>95UiHQc(kt#1YVMyE z(3!1`X}`V2Hrs$dRIXu-hGo^LbvGX>F9aL*>Yc}YtxfRFK^Gn>gzEcp6pG)i&_;U| zcJ7kyzcOfH_kPmC?q|>rL_=~roajW7b~a7rtMhO^Ml9hde;GN>UxM$HRUW3rH#5^PJQ~#5|DEus z^6-*~f_o2YUxe0YkcaSH2kJDSX)YkA=yo@~n;KwT!9=r{Tmcitb?dGE#R^JP+AOP1&Ta%s!v`Pj zadIzuY}I_xgV^FMDy!uN?Uzt{xtSJP`B<9VF{3H<*!Dqm0EaVjgg8!ko;6iA3Gjr< zb01QM>!dHOxjSf2SF>lkZIjRfVO_Wlz->x14oUA(Kg6bdE%ElTga@;I;Xle085DAH z;9Q~z;ZWawbL+6xD9ZtOZ{j3;KRKSOHs#8*X_Qg!au-TtmbXy*#dzR%Gq=VKXPBpQ zVltwy_<>=rET_*u+@DIqHIMW@yR&mwKAxT}$7z>HBd3z)cwG){5R!Ac`B&S*`i_OOy9w~DhN)8O(%qWM8Jrn+&6g)_N^G>ccNMXo_y?Jum=ZKoB3H)+$L$f73p|Ne;PWDM8`KX@rAuiY40UK#t!U(E zBoiL1{7QfUVps}tZIJ!zc%AcE_(8V^=aU?RvBhda9%v8^V8?y)0kD4$6lq#W#2nsA zco8|_6^Uf``f*8ys3ds*bP&C;DAn2XNzjvx2}B9YYoz7L_Jk|1PNlh+*C=k$@sPfe z)b|s!Dv&><5E6_y6>U=MWU$gf^Hqp{%P{MCVBh~wGizM(Ex4JEsf_*aGBw;^xNo)G zKiQCZYCTL!>u@Yrt8RrlM|RMoJX5k*XIy~vE^(UuMwUBVTAwjG?~z`JW;Yyvc8*7` z^zq>=v+%|I$=NlN-19htIK~c+Kx^MQA5dABIGNk6_Dp>HS*`i4ZU-n^Q>X(bcUfH# zZXGDRMX29$;UAWyIXnC!IG&SL>SZZD8mfcNSkg|UB8yjaRJVWu;+oI7h=?OkqZjXl)fyD>O(^e?JwO;$2mkLj#HYunbmNidmI^RkUL->@e7 z=;A$p+}gM%_eHM0L}baOn?fxcSja1;cxEhC98`;-+`f&_z_7(*9ur~@d&4wwge6nrq_cV0ggH@|z)5erd?uQ{~bm24n zQa#kYInbQ5Uumw&3Ynr%{*<`Hw!04!mMXqENDb^hpqyy;=4gF%1&rEW3vo{}(EBPN zvuUF;Z?Dwf{twon{^_>90K#$>(;dPIOMp8MKSRslSONDZHP%rzw=3FkKJpu9-Qshy zUkO$p2VVjF#>?EZM!L+WsnPVvu{9cz)v9OXe)v~aZHc@!?)fu(S_mX-#ddj3OzvEh z&7aCyeJBy>hI|v znZeILx=-#dyG>2{J+`m=J_46h$1*!a=-lpJr;Cm5@mcg}Zc$8hw1=fO*Xr8e)$^m% z#3$6}6htH;NsFJLzIeHrnASO8PE#HSTlHq9!?;T_us_5_0U$``$S|{@p!ATUecK=I zSEUiY58DIy<{km3gGG}N$c#N>!`JM<5)V^j|AEP8#cqAF==Uq#zRf|WeqfqrX6|K{ z;rvxcvuN6W594$Sl!1kV=_w-IpR$_+y#@Jn_v|y&yaK5Gh=1n~^B2d4D`y{`uCj0U zj%~(UJfG~lTMx5`0b#*Gh0wa{=RX)&=!$Ju^rX9v@EKuY;mZ{PWW^=ncnyS2a~E$4 zyZFytf@Ezd$}M^T(pnsK8x?~nGqsz&#$E^M`~GSdwQ{Oholil6y62uG*7)E)r>Jb= z8eYA~0Prjk9SD_`oQ3N^6$OrUi+P}P%no>HXkw8-nf{fJKY4w==zi=KOJX83b_ zCSP8)% znc4>}ec*wXUJ(Iq^$c|ulC}KKTk+wP%Z3S-XZ_O$U0zkXHY67$0v*W6fVf7c<$!3f zh4JgxucMCMewE{lG>5YMH_(i=+~5qTVtZ|K%41+7{U0t7!;EohrN12gi5kYS0iyO^ zE{PBLeO3X8enx`n*KIyr??9zpr&bLu3q8LA%wwQ`X51G6WkP8pRCE-#B~CVSiRbHJ z1UrW4{#}=F8cBhYn3z;$jcE1+0M>~B7aQoGXP8)(K;;PEfr41AD?iDBCNTj}}*ZGK>uH0f9)% zi#y3=otXd5k%L!nfs{4Z%#XavrWeNdw@^iQeI13=vxe-wO?vot&@VBY1(Q%KEqx)~ zv%XBRoUkOFe*iGCSvmVV%P6hYaPSv1YZzO<1lyDC1nYAvU)-@`=2=2$>AyH^p2Q7W zDkkkE{~~&RL%+?l*kqzMqJCReq<~le=zd0}+0XP7G4W5J5&XXvuBso3kT~4Od7YS7 zGw@p>Mm0cbkrvCjE{3Do*2sMb-a4uqpDiJCmg57l#D2Ye(P>{O_@9i&-38{mjSe>> zVmTqS`Yxtz?y#+chdNuYB#JdXv=9IKd^gAE!|`%{YG9HAgUSV9GqutAc}gNEJ1s!* zSqr<52384`SCCb!oueSD6PB|j8jgJsUMW&yMHt9lE2dNIyX2W%o0KqPNR&bNtuItI zjoE0W6EqBCt+m8%h>e0p(Om50h7q$->i>pHGR!n+{N|Vt$-j>oM2^GNQY`d&! z$@wi+`;Ux*WL>$-R(f(extPjJN9ld=f9ZYiAYYuaeAsm78xwwE24DJzeK`UhGtG=k z`OWOFhwE(q5PK%!z1i(Yh}*otzb|sM2ROAWP#zVl17=)QJ&`R#hc&l}8O2@^pKRwg zd83{(pHzL8b0GOLKR0yKl5|-o^>p9npGnukYlEcc7!n~MV59QD6TWe6(?~%v6Z^eH z(cU{&BTMEP2+xR`{ad_<_}cRdtu&3!$~5!Xl8O*9_)Ms0sc67JrTGLq1hP5%OOeT9 zoaPR@y6{R$4ybq`R%%BW%}QnDZ1v*eV!X`MS>-7)TeQG)U8RqlQgIRFM9T|@*Z}@8 z(AYCUae|p;`Psql$$Z9hSkx4IX}2i-+YN?#H6}24 z!gHj#Ji3Sh?M1rbqfZj7Ibix9R1@n8h4jP}EzB)z!lp#A(GNzWHRn@&SYuzV`@U37 z0n~UC`99GhVEH56a2UAv<)#qW49E!mF+N&srw^Qb2OvXQkl>7GK@?Qu(KkDskDTBw zGdB7L%RWsOj7%A7xP-w=-WJXdeW@Km{N^Uf56{)BguG)|2BiKI^y`$6}f{=>wT}hW^-an7j_`6*0_6H_kJXzY)02fYNk`uDE&|R;e!l^ zdL@jp-?PS_*_XRBPQA%aHPBkfO3_##$rjEOmo0j1ayk##N-J-^b^4WZv5ydlFeVo^ z&wGhcszx9{T)70k{phjUS!i}D4m6USvFP2`7H|LL!Fbeu z(NYG~a!kj8(F0jcp9HiH1H{@JpPPRy>?l~vX{&?io4>M`()RxSFdS4-6VoBP@?+5l=ei+gn7*!tGMLy^ zUkY*ZYr1FTq-?Zzde6bL@{&T*w}ae6eN~bkR8ea2)fCW0aE2~_iD!931>u8m-!S*G zB&H7iIcK7IeDfa7$^wgy1#ShCZ+kAkqeg0C{LX5RM6^23@agkstvzBeI&^}g4r$@; zV>d*Yk2(etvOKt*d5NucCKw^nFG9#MV7UqTW_9u_(>N(r<7*Q75ecg3HgUynGmXwg zeInD78L)Gut^wRm@2+8qy-jEE#SW~qHxM@Z?;Jlt>oVngsrsgWfI~g~#C&$s9O1cJ zf*|u4_W@>o*hs*zuqC?a&lhQHV&9WAv2-!ezKRER4hPAJ=d;=vGL^u*p&Vew1mE9~ zdn{1=?svF%GMV$`)`RYT70fzrpId`+bz}q8(U6f|L7r_zlWw_4=7~xzXx|AiJt_4# zvo8Gsq;WkbCs4&VwJs1l1y-X^&{j8oMey@%ZVf_-l}sSpmk;$>3j)P$BEfsAm&|Vg zEruV8z{&IPHmJf~thWT-XZ$ge_8dPqk-P3L_qc2v|D??NpnukVvT(6SmVXTeC_G$M_2RF1d!D8 zalM0Dq)d&RH?(V?5e%lOj^0n+;y!T|S%Gc~VJ3Nldy&wy^zZtc0}cTV7u%SH{x>8h zF_#S3V+^t)_b^(4Kj*r5o{m<{4i(a8g&%o-f@81WNb{{gp)jMsc43`i3(2Q&OiO#U zIGwE4KzJ-0m+P67_j|n~2N5oA&q9-pn?T$mnj8jZ2{q};o->zC9kLR(q5$Nh-uK6y zsi?F5U@9HU>7Jh~HbQUV(v(9i?&`bkz_^ z-4$>VN2?Q4%4!5{9!iL0%EH|UG^?Zj!(HIL(wqE0Pvhn3X^}!{t4D}_|BYVn-b;(< zgeb3n%^2b=JJe;f5Ki15{WIp2Rr{|}IHtN!P+jm&-fuOzTr$aPb~&r1#F>6cE%NKa zjxojk>ke~*wl@*(jg+euQ6RP%&Y!T({S{-T50nXqBPF_nw*aDP`HP z8~5*!We@V{b_xY1BdSHf>K`I`?&!WxP`q`C>YRV`buIDw(Q_s*&HqC9baOsySjs-l z5n>Z?n6p4kc-14Na8dE05=IJJ2D#B%Ra-VlqixmH^lZcB_Z`*Qbf(b` zIa}Km00XmIE%_2^YqZdxoO)pFd(RDz6wNPi$1?7J*JW-X6n{*ouF-LsVuLt3+A5&8 zew%~qCzbLzx8$WixNThTy+dtM$m`%;kym*lmaR9IvI8OISXwPmtGDOnps_$N@XU2? zT%$yGE?00RB3F#4hmk7KLb`|ERoj;`@AmS@eUQz%>nb8aNl#KExv5-tu zRvpNAEd4QN%?n)NM@PN<8GGO6dEVI%VC;>hQ__|c0RD7ZZ}1F?#+!zS+xt3zi>c)6 z5;l0T)x~v53a2ss%{|*`(;O|kUFNK9YgMM?MjuSFe_Sy>>6C?@^v;5!P>)QVY<-t* zkt;|^?Cm$7mgjv-iF3SsN^Y4Q-Wp~Dcq)Ya_l8eFL|A!Ef9`%M2O>D+ z(~b6C++|nqGX~GH%%*{CD`C5-{?3e+@;5Kmw`+(6dD^BEXJj7inu? z7jZexU3hbIXSDQ;w|UBzqC~D3x?4af#q9Y|%`^V?QQ#TCR0qe5`lc6|$zHzLNdzF= z9}w#Hg9~|_#)d!98?hfe6tB4s#*=eXnt)+b&QdRHimB_U70Tlmz|ukHFB}IKv=*e$ zsLm7Y?$npqa{;88J;kI=WfA*2156>x5K~hSxrnJUR=EPrivn_un{Z#RAACXz?!>@9 z+r?_XbbSJ%o^<~%*uDP9PYF;(?8IIj5PNidtbFs6vxWdtt>zJ0tmcbYPR7RjB->Nn zWoSU$;GMDpt+Xlp#ZHzf!Eq_CHegu^DLtBoJtFrD4=o*L2N=Wrt>d-2jZka>hI{Yx&as>(!$jS8ETN=gH6FreF?7x5 zHDLDOixHjV5t)7V$_5#b%iw{00x0>u2d@ymJ04XFiFx9$%WiSsa39vIVrIYXy4~JB z!yt^_aGOYXY+C^=`tkIZ^)M1-kQs|0U`Msi}Mue-tNHW4-bva`SH3mP)-Ner*bacdQem2P)?#(&SgRVBr_OjnI@mhEb z$v5!Ys6&LYD1UHWOI?VnMo2va^k7>7n?~fA|1E#|oIXq`hNQ5=-gZIOV{%FfrYD++&fWvV^ zn<8Hd)L3n9-$9KfDr7pAX0bGouZQxLInMKs5DTl9T)X_2shwa}sdl;r;F? zS?t8yH{Oq{zMLh6(J8{h!s?$E0}=pL#Y)$V#mY@nsGov@0@j0UOtwTeCQ~`SO*gya zkHyTunCyi1<&jTV^nxMB+}Iq{b=74@S}jmd*VIF~OR7M_r60^YAcoeC>(hzn4k+Hj z+P^6pd)cD}>dlT-W9}Lok1dx?wYZ$XJ_YA_8#NHE2aUIU=3y+u7xRq;>_g83dkFg> zOJZowiHRx~%m0nO;tuFi(Av+$8z9!cX*Y0sx0jY#5u()W+g zxDc=nebxqp+FcjX-FT&pi|sb6BrhR+h42tHD5Rc4xOQ3D*uwPh1N1x9$1&;x_z@b1 zHl~O4h->oO!VTZiH-m}0lC-9)lzxGZ=I#P9r*VmU_)MvW-5CP-5KY7KC)F~45EAbZ zrg(0EAI!j|kt;Hec*b>C(Kq;AEt+ji)Cg*U(8M>P*3UI@l63`-3`zvQ_Oe( zXe5w(3CEC>34k#iy+1G(Hbne#GvDTuy9Z%;f?b~v4Zu@D8k&H4L6t$+F@;t37^&C3 zLM83n2V`M}5Cs;XLM~G-H@9hJgUtG*Jqw%Qe&Yv-9_KVE0E#xPNxn$w!1VyQDi%oo zfRG!fOs|h#HWJik5P$JJjGn3?TBL(!QVSxM+c)~)ihJNJk=)_zJTN|T9~z-KI*Qyh zCxTjT1o=j~Qm{PZ3v%1)scJ$~milYw%1Dz*lr+^+p2iGC)8ctxDg8x{rVIBr{@`CCe+m z(Fpi_r0s~^2?(QeAibUC*Q)u~52%SmU%LlWNm5|EOau6c72VOB%*r1X?|Lf3X}IG= zNR>@PM02qjX9*bSq2W|2f@1<@SatrLPcYZ*r_+I7$rdoe!nb<71@G*Sd=ml@pyAuG z9gUgkQmX!QW--d4GyZQmLZ{K~JBmAXUysN(Kg(Om9_*#dSN-guexF)ij8TIs0+Isd&WJmp|V8 zdp9FKj4qHhU8iRKS`7P`SYA_xiMwr0d@%<0Bpwh5TXt_JB&i~@s-!Bd{a4g<{Q~`lm#Py669*WH|AMCdm6Cj7O7{?j^XeC>#@xQufZ7W}CbioB>{G3SR|1{TyjJZhd0x zh4`Nuy@~*@j;2CMa?m2+Z2bTFZ&k{+fSIachfhdWU=~>DSf8@9^xYXfrx~|8WTbuJLvF z8i7!{r{k1;x-7>6WO=)wh1;@^0P4|u|F}f(3GQ+&^WLL?9>gaf{8QDfXZLBoU^4aO zg+y3h0mE0B{w3MZxxUSSh7wPozIl}YS=(@AlxWvHCQKb;sytN{Q9B@mX17f;?YkO(@A)0a;8IQ6?|#-$V_{Y7~LEK|0HuT+`=YYZ|E zIeudrv`8Qqij7!7L-P_nXo1?`cK8!na+8=!p!A!aO1(mwiUK&|{;J1Uz>Q-k148%i zNk_8;X`abzzbnJ9d!nqgFZWPWL8ekGL^NU-<2}gk2ma;9`0ng~T)K+D9ckzuMA<9+ z!vqsxZ9DUMk$!x>zZGc>*S_*|JXOLTh)*j+L-&fFRXq3<23(LKNyq&?%2R&%&UL{@q=OI$d^mEEh!gaOCm^%|D^KE9ulg~(H?2KKN7r^= zkbJ>5{CgQr2G%HJhf#HPb--+(NNyCN`CQh^+~LX-z)Zs~ee(lv(o?+J~@+79N8 z#$P{E3ML_eLGW787IJ>_-0Z(S0!__~2@05h9T$vR{Df{8ztkjm*Y4qkR{qrHAFN+- zrSu9L6j0iH-Hv)vOwBS`KBF&+^FK30zs~5(Cg84gqzYV zyn z)7l~US64ErW63&q|DB`5Qgk_XszO>7q`Cy5wtvKSy5OIa!4^g0OQ#@?R$}C|aoDyP zd{M~AvFrM!3px-cci6dWAleDlJ$+Iy!J~GT?EMkD(=%Fb*Wb|K5ArP-xM@r-9@W=; zr``fP0G@pDTCniKzbLj?_5WKzm7RUKGEpa0a1snm`b?gT@Lc$K z86Ho;vKh^T?=L}E{W(5xNFlLltY~K;8Ng zGtz42WdRy1kpCIoB!;^hVBK z$lL%1Bdmf`>q-x`b}1BCl+s>yEa;hjozm^5S2PNQpMr?L0plMs+q~~O4U}8}mkgwo z>gYjKhn-vu8K{GHONYUTywm;m4&KknlGvj}sd}GojpE`a+r@I=jVYcT8p;XNQ5Rnd z4h4U^_x5qFVcyo|ikX!2YM?(2NL;Bi368OBg$);5oUx42>_t!-h(FcOat4d)Ve#uY>{Eufw!@#(~zR)K|k*?rd_hugdBLAFym0Oo27qio6#7n+cn`Y1cEP6k2c#^X^hIeyjkO!Yt z_{DiV@7~mh-9f_#s-{80)tc6#&jF3?)bPObDkBgCz!DPdnRCInN`2@yW}w3?X8%WO zVx6{*xZ*H4KR@4TxfKsAPSiJnx64ky8jovtNtDk33K*(b@(C724Tt@yD|V#@Y$B$W zCnM2Kw(in&NBHcgqs%Wb7CNP=D)AWSgY()3GtlM1EX@ioF0L7mi9^esc+@ z=^AjH7>ySk?3rL zq=f);AdeV@JN=5uZpl&IF6Zc;pWthYNW#U?*CqRCQ<33dQQ$g#bn{!e9NiYI-6tCj z4GldPl#G!yw=3_V4z~-p!5m&g(C^qFUVV`&_(iN-shQn7S;L1CkX&n`Bsbf?=FAp7 z33#i@AQ?9HK#rjSfb}n{+suY7!3ApNetZkPn-$F^KSMx1i1yg1X-~0_4 zsdCAR@0yjJqs@>vJYrMz#qeM%$c|{LIWERLH8!V&9=#2F+3sx1>q*pek>GKtKIup{ z<8dg@GnmX{Xqasd=HTGat8&gTh-nT3tMn;I<_-uAoUJDthi$d#JbMGTa@2ej!Pxgm z*^P*BEBxxXweU59af3~Ey-n^SX_Jf7Z|&K3?W|JqK;o@Yt&>6=SLRtV`7JXQO7O4g z%rPISo3BgK93caZwZ`neZZV3hB z-6p2j9sCvZlZPvl7D*TR3UgYgWJb0J+R(gPJewcpVE9Bo1Zzc9hQP^CN3ABIB$BO zJnL?`^B&;bR`-%8ad@h_^;YJOZPVipCRtJTc3Sg&Es6&{DcA(zhn#bVddbDs0Vb)& zr~#Rc%ZO@>?zqJ2fkRgQ4HtV!3UY{WlcR?u*r|a3P}1_31BDV~|0Mb1Z@6x%_fSVi zrzQ&wd4DzC8d{B?00svoJ;}=;v5c`%vNHNlGFn zt4IfM|aG*=~m=-ZRnDJeY~R=!EXb!b+`{tS-t2O^E#eKI?>XoK8{I7=>%k`4m9}RNUv%i zd9ofa^VG}gfT^dETnm{A_P^srY()GHQ8f&WKc43i&TCl6uZeP!oC9z6OdtcA)pYto zRTuV0xLW6>|}vWZRFfcVSoIvw|g=8j@XF9-cerpuSD&{6Gr_1;zb7rj@? z2CMHo-nz8lOF61tUH0s+0wZkyU>q9jo%c}roOo z@$DRN^YMy7f`By}UBWG>~{snd=674{hN{Nbz=-|D&RLqE)^ z5*R$zjUMaB=G|M-VlXaMo=8i-)zSRogirgs`t@u{4HGvsIMn#I&(qzc@mi0PoncFM zMsN|Ph98~0R6KLIY>Iq1TfWlmsz;Ltvtrvbk!p+egjG$R%Zt9|ZPD~+p&PS8ibkH< z-iT?fHzN#askK}U-y5IKZk_5sU2R^XB@vJIhBOoqqR>W~6t=Wigzpy(c8Fg9cV7Kb zI_#gfNAwM47E`rM@hK0JS{1JYVaMLpQSi#Luenr)*%B@Oa?M|5EIb_kH!mf7>O=qc zfESGPLrG&zMkOWV8hBk)TuM@DVzk}rk_I{DSw68Tp{WiH8qIi(BxI)8<))=I$^b&& zy~!gCu%W;~dEfh*h;bbz$6dDc{=84({buGkRhzGVzh}dY292u$hGDuQ%K? zK6o!JQZ^g*T-n5ZZFh#3FJgq*Ym66X(ezhd?96G%b(`7Uo3N5`?dM!&w(Z^nTWilE zhffQS2FlpcfSkevXQD>Vk!9&SinY|$Q?CkH%*VbAbArhhR4+p9#wwqMJo-jB&!Uh+ zKD&evX*}`4<9Jt@mvsFwWI`V}EF>10FsW!tYBuXt0iCm_pcOBD;R ze5((855t)frYbTrj+?i1N2#Pq#T}Q4_jK$9r)U_hn%|#a-5V*hVF-ETSy|2@by;f- z<(K?>S_CZF>ft-heTDNV+zOJ%KO#NREv-3I8(ozz!O{LT4#M~1pAzwsbn^z(1`XKU*bw$Tc+-_4XS}_=T}|8>9hYdd zkazrl?Y((8)bHCqK8lJKl~fYi5E2oxYmw~x2w95Ap554K@lHkdeJlH5?E6{?gCYAi zmKb9nW-xZ&`!#xhp3igq{{Q{;^v^UMj^_57>%Ok@I?waE?=s8N!*H?7T4IIp6`s1B zoxtbZwd3bE$&y-V9^?CdIflMcx{cahDlX_M#`=(T3{yP}X4-M*C=+AE;%d<^>Uwbc zDy4yvqMSqGEBT8+wo39^|BZ_>%Ci|RoyCX~dXDo|caol!w{@u8O&y3NpG(rosILvk z-iY5M2F2gR(L4p7JPAX@$JVI=iMfI$G^TnfG$aVf-o6G~IR&ZyXGsC9e8R(SW+%Xz zcu=%Z*wy;Pv6koxQ?6djdyXu z(V1NYzAvr|RH1dvixS6-IVGfYUuxU3dj|vagG3^NY0!b(N^(C0Gi~QVCM#huvC5`W z#u{8=%HSccQWPuLf)IFS&dwzmvH4qGlgwkCfs8!GrY&d7gq%b;js?k{)8DTPY?pkz z8F5|P4UOZzw-cw49NkD=Ss=hC5M0gvP|#~d^;axERqCe+LvMc3gk(WsQG z`Jp_GxVfL-@vAdIR2K&FxEfMfcZM>+mScpcKrSUFuvvq=;VVTsF~_%d_~P2;U5BYB zC)uQ)O*RGh_v#oeV(5e!8?bs0nX}&hImsMRjmIm9*uuvL2rc3->e^Uv1<}6GH>bF6 zGu9+f!90TGRPNhPe|z5n@j-im5O9G346{;xb@}_diOQ z3{E8b@2|1ZNtS563rI-+irSTd<1Qi;va#pO>y2L`#JPP1`MA%6;*ud{lUlvg#`R^> zgoiQ|y>*rHL{^zOjtL9;<2#a2eSL7OQ@64^E<$G{&^TilBP*wJBXwC5H2JG6L>(>U zLZ~=yjI5~PP4)3ZLrdXQ3twoHmRU)enIQ*PA2lpLPTFb;Lj_NMMqK)$ArJlqmYhV1 zD49AF|M9>;Is=!%mzJ+yb$XGp8JtO;8jD~+s_eashJvu2b~m4jns?)C#)NGToN_Ej z#Uib)>WNZ2gcPFny?jjn+fYz$eI@JXqXOUa9|aF4xo+u_F{F8R+KIr$&8dxEH_(WY zM;uGMcijzKvCg(PM|h99Tox_(=Y@VBkMRCETok?L@3K7Yy>PLXwnr~jSdJXmjL_DQ zWd@dT))&s6zs{YSC;}KUIf>Fl%GBZ4+_j%Q%Q<}Np3KMdyj>t7owgUts!0AGv1fAJ zlvZpAJl>NPXw;>w?_qp8qbWsGTv=Zvs2iH?Sy4Hm0*Uiry}t?sl7!x|J8a|t+%ywK zDUkfe(O1fIa+Ej|-M*%)CgtfEd1=>ew%hge_4ScXhT1ol<>+`$&`FUn#qMb+Nx+UQ{mSXcnD`M;mC+K$StaNnb=x4j4m5cb zi1|fy^%KC?+1Mj3fmoWJ!n8SsbMB_-Nf zTG`tX-SX_0%5E0?QDN7S%ql!?7vkE6$1w>!Bc6?Yex=A1ADa~K`U+&+&nzpG#8#F6MXi!x5nSlkEoTWq}-o% zqSsVs(a-8TBGfMZur`z~B5_+E$F}2~RsL4E@}ln;QNW0#fOgdwoG;g|bD1}@*r09! z@-OVoo9@A#tB$Pn=pyg51rfF|;c5=f%X2fwLS)CSq7M@SKYlD3^WL5mifx940gPS}d3`x;D6YqI z5<$FhzC~Y3BW<5(jtC&|AqGP}_>ro~)C%n(rzMRV3eu)o5{j5fPx)cZ+8iCq?50At z;YCX{7Hi!a9^b-MnuFdI+0I)3veAOWE$4c&!2M>9KgMLPB!`Bcb@c#jG;H^%zBzbl zMx^tmSUlX=?C>#!cI!N~fU=_crQRb!3b6#ssdr93i$35&4?`W}T*|Baa8g&uqt>zfuy?L`U zD0o05KeWh{?F=t*DYk24~pZVy-7=otlE6lNnI)3DX5PcXV>jwg#n#0wfF z7S1KK>C$Z7VSoh;frMf#Q{yVmg0MA<`$;F%g4m_9=ViFFAMP|SXo*+ zt^SsqM;h&BKMuOgRX4UjQ3_n2up_rAwdI7RnH+v^n}GW72C+@BvMV`|Ow`*#Ba3 z-&tu|TmC_hOiPmuB7F$FB%b!j@y%J@VD2r9BlpEM1fw@810A=6YhwY>Y1NKnAP-+jYw}zL_|cam~%Ej6(h_2#g4bR zxaZ*QkN@&=1qxaaWox$KyiY|Gew zkwUGYQ7vuv6q1PtG1&9i=cV~xlqnM|S#>N>kkB}rn)5pB+)1?V=9l7i1Xow=rf96Q zGm6$zS=R3P^Ar`yH7ypGf#;WmtuOZ0fX{t%&La)__(b7wFR9Ng;_$K&hmQd3d~M~c zdj=XOZGpjuucz-Rl!#>E(n(W1x3yQ8q&4?K#v(IJGpAPaqi2kiB6PWTe`h|?Jfd_D z49u*1_0L+*#s{J;v!h5o?HarK4&QUxN<1(RbQJMWHQ-HX7gp2}$LFA9jgPtOhf+R;?)4uyjATnTg06LJ5TJ4dBIl-Jdb z36flYO4icSnu2e~o{o;hfM0*(M(Js=7+;@yt>4iVh%gT2u0M?*OThg8?viU=w+Epn zBh#XLLw>fnD+QkR!$!dnQNDw_uI1j6Kn&XR=i)WH|C`*lGnVe2<-pdG)Z`AUH-D)o z*7Sy$W5ngLHrbV~t-<~K%=#}A-7+WPh9&RqMLe7w#4LibS+Slb$1a|s$I60rEYs(c zA-pn^mdE4);X^xb5_8S|-nL$)Qx+U$n5%ZPXZJ|ZH>Z1p}eY zj;B}lYms7&U7NpLt=#zY5gUn_?$9Db{h3ZaBeal(Lk!e}y8XS%^&uVXvwNV(ZdMp6jOkK~e9lB=N5fukdZFt<04yLQ6 z_VzM^-k7$rY249OW^2CFTch9COj~9)Dw2T7?4MmTa4B(0lt2^?cMWQhBcq~xo?;cp zL22>DQk;jd0T$*ysU%B~>_!pz*|!WTo%?%){kgoVr7my~M5PY3`MnRBFXjz(cE(iI z4cDGBCVE!Tos!n(PQG@rYLa#~Dx+AB=;l#7f|20-!3$t)CwoLVqh%;*>u^`LdD_#D z!_$Kalpxkg|6W#HtkuNok>kP5&Fz5nQa+{xB{bMV1oqG^5XG>3W|4ex9)Gz{7gHXd z5`Cm&;2aSf8{0EFI{NVRLbLqOb7R%;S$%vntqAviy%+*5_vBp~%k^h|2G6rw0u=>1 zQWCTxV(7-7-kTSVfPGnVc+3}{8UBd< zVJ~7(%nOB&x=O3D5r|QQVzvwGqv*NPN6#X&9*9&NMbP*@dp_FJwjG-g{?(>XxQ-WJ zK%?On5dWlDaG~AS8%67-EKATePe^-6FWGa_TiF>^@u~g-Sk3Mkj}Y+UTT@@`dsomO zRk!C}Qe6BB41iQl$6Af7cS^!p2j$tB=SxhMoNzjy)K=cL;`T?bY8Zmv%BMbba;1ek z_pWMnBI-q=!|Wqrrem;GY1_zQrkV5?g|Sj!NI%=VN?ipA_A6}!4TnDkIr?I8uU%(4 zQ(^_pgFH^_czf3>C@72!))qTKs<8}(c7iR)rUzzLRt{kctcM=j0V0Mp-R_8dQ$^DN z=%iOq3V7$w?Qhzn*~Fg7j_GGs(*`JRHs0cJK@;6xMx2URvv`wA>qB)yD=RfeEiAsD z?F(Fzr%`W2xI=||!bPO{J*~5{GeMp+A@zFDy+1#6Yp18aZG%sT9l2R*3T0p^W4(uQ z=R?iR#y^XUW*%kpRHK(%{Q|YJ@n;r(UJJC*MQxzWxO_IK8NEo{IIoFTjpR@3H8YsW z5E1^j_#?g}U;a@j$j>o-)Hf|um}Gd3vnO=Z;O_jKA;WTPpdm^0nZ7=9u*kehyEc6; zYR(XR^c3A8WAKtpAH&j_F0_ikCuDT1N*nONb2{1fH{@)_YQ6CHm*4j@R!yA1>3oJy zWa(s%=Xa;V7#lYJ(WiPQaF=wnmPmEccmWfM`H-JuT(pWg?qFCsoPeJPF&V79QA~c= z>VQNjlRt|(dS@1xG?gDUis=}m6hPl+KSsf)!;;zf#lI>aN5=@7TmJgQaafvXQUwk-&lho^qCV_|^`x=PWH9!A#5Bz_m*>RBj#Oyld_ z^tQq_F>X^eRTjQ$DXMxa^m}@mqlU`0iBgXxn+|t|=~(sS)1=kmvAxn$QX9r(bHTc@ z{QTt~olsCVJ5x5TjPwf^l?xXxSPd0hZ2h@VmsvLIu6X?Xt+Gm*5q7P>mvIXh7(OCNuP++6j^S7qD)O?J1)dGx`&Eh*1`W2Al$S7cl*Q=_ zNTy=sRe%-A64wWwutyB+`JJWTdt7i~Nn*4T7mx>JjnI*M_PgJOxeE`3Zp`HSI=_wT;pWjeN}767kxNIX~2pb zp~_sE9H%U%faY<)|9HVKVNqR(<`xVVq2l+IOy%hmVytc8m`%8Vt9B|oXA>6o zsntF{X9+`HDJv_xjD5I!hfFf;%0s}JA5nr@4Uy<_qo91NJnt{C|W*h>_mEpt>AI2p%?d4G=A z^6hsbwVl2e*6bW%-^=jNpY%6Cu09{@Hz7ZAf3X?EBLb=l3ex)HzckMU83=!d<1YCdlPdE2V zs#>HeT^uPYK4%$<4lvLAZgT2`!qN#NeM`H@j6J(T9Um?1@SQr5DyCYgB-NKMUuJ`@ zXkoBO=*7=tG>81?-xwZ(N~p2jBDgLD2K%B(BoduE?;o{j@Tbu$vrW)Hv$H;I$HN-z zT349hU{1{mRH5&xd^+QucA2mG>d@kz68D#3=9|@p3hxyX6AxWz%H48~ol83t(=_zM z1iYgj><~C3q}&0j-%>>`s(Tv z@ZGL1Ca{zl@q?5VByc}J=8Pvuob$Wnv3@}Cr9reAAP})A>*2!TI7aU+VOgUJRhn(K ztnb~Z(7N^0E%WAgj$UgG<*a*+7xZmkz?9}L-G{*(!YyVmTZU$Uc?wS3$geg_R%0LJ zQcbTRtH30ywC%{f1fRW4ZazL&pWC-?Iq^Z+qSJ>W4Z%c#_`Xf3tGivbARuzA7F6;c zz{x_i5E@vv4ka{PN^4`+*hs>(}f%Q5#?BtyL>A2N9PLK zKDIM*oCv(DASt;AJ5p~oFnjTLoCF?7`JE~(NsB22-o7gO<3)HpLe{c+P} z$4_RM_^j;gpi&ISX)|v?bHMmtA3TRQi;BJ-8KBl#0^kSC_ch*YNFxi7M8r?}C%9=9 ztf6?kX0H-Yv7~jeVR;D6dj8{nn70o@BHKiHll`a~5+sWdQySv ztV+Un=zv^HX1-S%+5l&NxTs*@9qozxp}oaNZWe#>VjA;`M(j$OO-nIV85m*SVlS%{ zxr($1i!VzGgYTt%YjnKEA?}C-C&Ot{s1#Aw5^{6>@K$8Z1hY-V%kS8yY8YmEd4dFAM(!Pw-e>dOQQJdCnl1Xe zx>+W{l5jz@w%3P^7}hng5cr-FrYr+?Ta(5G+NBfU-$9yyK2x>(n&rC(DN8z~Htca_ zJeyI>=e#W|4h1A;ey#k7V-XZ}ltbK_mN7mw9!?u^x$n@xJW5)yPK1{x4wNxl9&>!V zd1|}Q{44wdYsBxW{&ZT$<8*Z4NlAp-VAW{;`$cB$T|YlCFdn0pI^jVJrE=efHx!Yg zz9|~^e1DhRUyUF^93U1n!S0*5sNT`h+xReEIU9YKeBFr*JI$#y55{PI<#*=Kc=z$A zIF2n5M(n@N1`BYI2F{+Q@|anhb}DsJK^N^BP*SKQPlY_!9c0Zf6T8!O3 zIjloeD>%8ZWhHOxjC!D4c=n9Nu9X8^ntjpD$R)Mr`U#9bt?TjQ$FY4F&2**T{dIfJ zB0EAhiS3kD2)1$HPK3FWaSixxsqKYt`nDCa`lZ&twRH?|@FRe&#d7-#N@oC$mbmSR zg?G~QnrOLC@DhVI{k7D%LyQ(!z;#a5b5BMSmM(}{i0102IdPLK^w+P~$daXng&IbiXdS1i5IM_%{O3!A6WpF4SYW0H z!6E}!dJ3!~dWk+LV1j1_fA&YY5~GOgje}2pJ$EzTKS~TZ(d>qKdJ*Zg}1? zSo*0q0+g2q4z7p=?}`M3=TPZOjAjmFzMuigquuB0V%N}xH0@x;xUp~sT2~CA-S$0- z)(Mz0gb+m21P3%1luQr#)d$??^MjI^Z^wa|p#Juq`^*2Fxn2w*av>oL&=bXq*o~@~ zQ^&yselOR?=1C~*5zlbfOx;Gv`A9j+N$EW#6xewhB3dm|Z3ye06()))(>eH%L!!An z%gUU%!M(f%A)eH-q^R%hEH;TI6QDW6<8WCZtIDx?6$8m<3BD71zJr5$DVqp|jxV-U z`~VNznKzD& z)<}5kvTJkX5;h$eU`O@AUI22#|Dva^il1%UT6=y7TUaOnd!7g0cZ-f5%97x?<&Z%Bxhq|BYC6&D9w+i!#&rexXKOQWf*e! zEM7?4xpv;s_0D}w`xuwloVX_T5HF$Y{K?L6GI!67R+Sby;TG>Xv#bdNKuqNr(R4xXhr*TETnx5Q4wSfCs1OAtV zVxeMa6aO*^tlf>L1HPYkV>=Z@DWBqSHsd?eJSf%CKMIIj!S0`myDYeD&7#xAAKam1 z2>Dp4Cl;4q=2aCRMF{DW;w%wD%X5fjkk`H6qq4?@o)a?Fzd0=wG|fRC8^B3PS>u!- zULW{14s1BUO*FW?IT8~!wmnLAg4ipdiuYo{up#gbrFCQVv&B|2zs?(KTko}?k$drh zDoMy4t|ocehhp5iA(9L*`m7NI@E*xzyeOP9J>x^Q8;!VDbu`vg<+qE);>WHz&eYub zRHtVu-0Y1nVp=_na8`!WW^lq(OPF()JZA+j0l0twKjkEKg_3MK#|{edz&9ls4NxO= zi_B&>CWHF{v6};~6UzcHKH$oL{hRTPqe#YmtZTTDdT#xPsGB}Ry2NlTMOOdF(IQh_ z!>n?JKFm;OC7|or7^P#!Kk*+w{24K7me>T(l*i1|KS3sjy-;T9SbVz9i)nx6=(vmq zeyQBq?hGJNH3NF{!FV1wgdAZr9UIe!pf3=`e?OmA&8#gt1;XCh$h@u~7V&c*9)&A$ zRE=GUQ1kSt`BS$02(iBl<_I0DazYq@26^S!Qf`|Vf=+QQt0tjpI;HFIrNi%Noiy!r zL(X$`-Nr{qE6y8*Fr0MJB8v@blVe>l)29BTf*lf?fJDd_?-+SoLt!>y7ymgZ1Pj`% z!E)E-f_l2r6d8k?O3d2z+LQJPwihou>KA!G;LdvVV|z%-^*!-@U#1ggKdhg+ft`^< z+w8uybAcBzQd=PsubCGf89SdwRL|iAUFzX;APcvh7&8uA$gqvPG#bHR5w(DE>8P0^ zZ(}VD88%d61Y{vW_c0*mKv&U;fzYcAh9W4!Iyo!33F%5PIk?uSc@QM3e*)mHc81`JL%k!8zwb_oO>1C|WmVX7}zs1jxN?r4AgFi23sI zZ;2EYbaVv5QRU`zT#5bU64{&ksHJn8R1aTbO zyHRu*L4^oJrx`1PIg^x+o*d30+TRsays8kwI z63|N^wtD3;#Pvc# z4OB0~Y5k>IRJaC5lC_p~MZrzO-|hC45Me>#bP7x_x5*N$z}kX!>|U&37UUBe={obB z%Hs_}lJk4vpR2ky!+?F3u^hd@d8T7WDzeuAG=;(qd5HaJL43d^ahFfqQeE0O2u{J? zoE&=(y{__b9Lvkf`VBfG=RRHY*@7n4?xej{&a!LwVipV==5Ck-=6PuU_L0`z6q-DD zZ#RSP@`g~B=`qHJC4aNp^$0ky(n{WGu*+=8%{k&C4lw3zo~}O_QfX;k*zW4JvTN86 zvf{`ckN&O-q)oLbK(Vtx4eJ3YB?m}H^my_?&jb7WO=)s8-?1rj-S{fb z12o^1rYlcd%KxkpZtk&}^9VSV)2Z&H5QC)@6VEbupZcTLJQ=19uOLAu-82oQ-lgJ~ zx-QbXc*05fo!umdXfR*+LGW6eN11KJT8{F0%_?sF5~)o&bNz8S$+L>m2*P9zOu?`% zAqHYJQzC$$ozDYU(m^fIhlnDu>yjT``wfT^jSnnw;pMwyQ$FMFj7r;_G;_B@%U*z&&H5P`#3g zzFnz2`kP_uj-$QT-ZLX!(MUP?#FsWUX?CR|28n`BL52m8*jB#elr9#s>0c4D2@U)7 zm(X%X#f$+y2^4D~a}2$Z%fiL7MnQ_i2g~1HJ_!YJz3$f%r)m}~Qan!RV?j={wymOhlg(_- zYor8dP`%w#&RK^rd~~VJD~ubnGW-UDR%||}$Z5IZXjKEsV%GMy$$O|$!WNh)ojUA@ z1cN|tU*FtxoLwJKWwC+A4AdFjl5Hi7pL|ddn`sSEI)LC18}~gt5;&fo&QSx@Ey#!J-(XB;9^hivcfC2-m(x?n zG6z2twKvm249aZJ%I`tvd{p3Zs6;dAK4DJ-0GF50jIa(lXA#;ZFWT}pye*HhoYpzu z1k+cj)c$il=rx`ko8KS*3gRkk=`;H+Xlg3>kHy}jf0HYq+^`QRA>{G@zVOKbvY2Z)` ze@c4ibqz@MdilnFQXAuk8($PGiR5c4EDWUnw24BK@JYy5Tds`v);)+p1AL@*E<0Zz z5~+n78KPHaZh-qhbt7W#75*~4{BL1VE2B_DuPY?Hi)hQjkZ4@#-1M3WH==!H^e^$9 zSzO#B+5B}LvaSF`5Ku++6xy+{3XIk*R?p=Iz4F&7qh4eKUcKTcfA{PJxSjsBTEqSp z{kufH?C(ERG=Jy#M7VCaX&OrKU#Oo9%P8h>+&i!O{@L^I&oU-Av(>^RnD;rhXWwb$ zrxjI}IRdsdhQI%9?ccB*>HkRU4VoZFrstHPJaPGNP@ZIXtsH+(9pVYRylQOgc3mLL zt)-nE0W2Z@$rGqIUG3f1YItj+<+k-~v&qv?U@`pY*yddt-@ zVaL-JnX#KSpetW8uws61<6|tz94U@!>V9eHJHd(*<0K;Fe!A zkz=LGCAcw1CE3?%AtFiYtAQ41HX-#iJaBUMP-%FF^aOvj;zj8s{^3Rl`ZV38_t>8@ zO|&ypvAcVdhbctLO%W6LQX{k1W_H2!cUOhgUP;!JP)3K>l4Go-N9p6wm(q52cIbyi zyZay@1aqLA!v=%ZUflGwec}SfE^eNqn}tAhD7)gh6GterF0kqm_E0Z$F6a6`-_Be$ zV*BDcRl8gIy>G=G$CI0Ss9d^0{4mz-30(h8yikWcYLriQ7#Drz-bWYAds;{3?P;*- z+G9u$KQjpq<*u%ov3i(oKoM9!PB~oz47(~lg#&`AvQmr%R1o*=MWHP$VecW-*^FIb z(#i48)reA!KzWuc?Bfg(a-T$8dxH10BX6PPxU=RAj=l1i`~Dq^;#oc^)KWByDom;z z1agN;^M^*ks0{c0f6Q3fG;0jO=Kn9=8&cuM5H-}h&{N=#K4`J(IqPn2dR`KBNQG48 zda5uW2-fZ3_^|7p*aP#t z@KW|$*9+YbB+f)IqI2fO`Opa5Xj{h_ax#@TYkT(he(G9CukH8vEqlS@=RaqbI@162 z7rU*yN#uw?s~LZIusQOJ_>`oQAdH4aD^RSH`ZK_^RLstfzyhNK*6NxXtM=Ii=_*3*PSg2yzC8WufppHvqO zfpf)Z+2P5TfFq%8SqPv0nWQeqk_N=EN~-)#7HBE3q)O(44%k=K{6QI1$M$wMfkVAl zSp=J^V~A)>IJ2;-)-wC(A)T~W+%>*kT|Yi0orziL2%nLuHj(^VT7TZw>#FKmJtk?H zlkfXg6yJoatPPIY*W2rh4QqIWNvt7FQQjIu%dzpVGfAQ$Sdb+0{Vb#n4-^_JU{67J zbnNHbhzL@+3RulvPz&T`g2@n~;Z-2NR4x>@LKlVt{O;xc=L08j;5A*jcOE`fvJYQv zH`mVZFl9{ijv)SGyNbI&4(sboP>LR`yp9wteiMk@97qo> zWw6vqcrgx%L;|78Q2?*KG-5~^5je`+N#VX>%en_eO{UZ+)lj>cWq2ObQm!9I6> zLEeOi%0%leB-F$R1gGe8v3z`z^$6|?7)W5KgC-L2Nj|k`Knf&5>{2WA`@;qj4gjg~ zg_vbb+fgZ8xTe#_M1a-ONQLdO%clZf#=%xhE_1PJdJY58&@GS7@>llicN}D%2{($Z zD3aO<0Mq5?(edBy(tyg4gmc<->nEm2SI2t?q5fJtdJrD zr;65<)5(<(#|O)A`n!3|cVFO07OOMAp|TE6b};nWb%tt+xXXgtwcig*UJ2wq-PLQH zR?!*l47ntLKc#z}vsv@*&s4O>KHC?U)K~g)r^PNt`li}*1#L5JZ^ z{y6FMZ170RZsewU>e>H^%fGq|r>F`%_@%mfh(1=_c}@$E+!Z7b<$1gAL-7Y_%XjZR zh4zK5_guK0qzZl@J2SKMq{v9J^v(qR79^ztGdVa4Xi4M=XT+7ZI<{Cg7)vMJg6ci=IC)VAzOl z!n~~p!eD$YNRd^+DYPD06v7I&y1jdbLb<{gCio1cl70oTAbC*L8V$y3t|RsViHKd*Zik-)ym$nEui^ zUp{hk+xFk!oO<*j3;4#2i74z62l?U`SHNTkzi9QxI$7pG5M=*CWzlH36 zFkio*zh8?0gTVO<7v{q?RerBDv7w?2-Q|JEk91iWNHG-{gj{A?9$~R|TX{sDY{q-D zW8pqOnE)}QkZ5=$()Kwji?y^z^6p}0wzFQD{H)g4k$M;N|FK~%!8f@XqgZI2i?cD) zil`3!`y~*gV)%H+5$Ww+?}(_Vs;D!R!V7btoTvpl>obCOr2rl#2zmg+s1-QICRW;~ zc5Z$?;>nH5|Ik7^PxhpZkoERsIt`x)Xnm<2wzBu@TR1M(xl$E)cEFcGYE%OT=4R(0 zwr2pJd@Pz?>54N-1>zN1z9s0L`1H0}gBCej7scXc}R5z=Ae-)ZrkgN|Jv6FtF>FCcb`qj*=jXRm}k%YR0QLHahs84VOItw zBQjn+nclZHznXddonBF1etRsf)3@Bhv+7*uL;n-G@-1#4r9Qv{HoPpf|7~@8>=1Pw z(D%O`Br^V22Z>BZ`uU+&fB!?ufI4c8;_C;LEE1VlsQ{9?Lp-Y)cBr%~_cNVzrOa>q zey0DMIV}f_Cjy;a)p2YcVH%-basPF&5PBBX)=?lRzAai5;<5cd&74=3GZvKR?>)9`29I#VnSclC?@`Te=g^R-f zq78G?Tno}1m6bmaU-Q^nodr%UU{Ym16nDTF!j|nl^`TC|*Bf1YFE2CmwW{>qO0e@U zCi59+DDw@y6h&D*;-c_j+D4&RDjQti65-S1#@JC&@=d6?pVQ7hO(IfG@^Sub@o=cF zN+e@FN9X6GINdsp^|_`rW#mXqt;%$&Th8^TON$q@D7yD05!-mP_E=nET;L3m=%5Fk z4g=)fVM6~w9$EDP?DWY;&^S1x&{yIUJx2OETTBbLBNoF$7f&kW+C(}oDlx`;R_vIZ z`oef~2=R}lzn(akqKcgPbYh;FcM@i2|6QzU3^zm-a-LTd?`sVzHaEap?J1|nmLV6{ z`s=(yftYSoHrGG7vYbp=K>qQ+71o!3BGr_ET5>mp^zFU;|my2F0sXmfvCGhXbJhA>k!$t zbj;5rBnR;J{36oQV>YT@P~xD35z6Afh-X;7`O3-5(6@Nx9z$(xMFr%nMfvPnu) z_8WTSmfDRa8l1MCh6N0}@9tZekz>PX-Jx-n`Q$gJ9KiKre?`@QXC;Ao{DuGcUna#? zcA3w6^8Pos`c!w4#h)M7n-5C4D9G#mS{3$>BA$e+5QFF{^b LmL->f@F literal 0 HcmV?d00001 diff --git a/selenium/base/fileserver/go.mod b/selenium/base/fileserver/go.mod new file mode 100644 index 0000000..7cd64eb --- /dev/null +++ b/selenium/base/fileserver/go.mod @@ -0,0 +1,5 @@ +module fileserver + +go 1.17 + +require github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e diff --git a/selenium/base/fileserver/go.sum b/selenium/base/fileserver/go.sum new file mode 100644 index 0000000..526f4cf --- /dev/null +++ b/selenium/base/fileserver/go.sum @@ -0,0 +1,2 @@ +github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e h1:ogUKYFNcdYUIBSLibE4+EjbTJazoHr5JsWWx21Lpn8c= +github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e/go.mod h1:cbmYNkm9xeQlNoWEPtOUcvNok2gSD7ErMnYkRW+eHi8= diff --git a/selenium/base/fileserver/main.go b/selenium/base/fileserver/main.go new file mode 100644 index 0000000..1790ab0 --- /dev/null +++ b/selenium/base/fileserver/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + "sort" + "strings" +) + +func main() { + dir, err := downloadsDir() + if err != nil { + log.Fatal(err) + } + log.Fatal(http.ListenAndServe(":8080", mux(dir))) +} + +func downloadsDir() (string, error) { + homeDir := os.Getenv("HOME") + if homeDir == "" { + homeDir = "/home/selenium" + } + dir := filepath.Join(homeDir, "Downloads") + err := os.MkdirAll(dir, 0755) + if err != nil { + return "", fmt.Errorf("failed to create downloads dir: %v", err) + } + return dir, nil +} + +const jsonParam = "json" + +func mux(dir string) http.Handler { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodDelete { + deleteFileIfExists(w, r, dir) + return + } + if _, ok := r.URL.Query()[jsonParam]; ok { + listFilesAsJson(w, dir) + return + } + http.FileServer(http.Dir(dir)).ServeHTTP(w, r) + }) + return mux +} + +func listFilesAsJson(w http.ResponseWriter, dir string) { + files, err := ioutil.ReadDir(dir) + sort.Slice(files, func(i, j int) bool { + return files[i].ModTime().After(files[j].ModTime()) + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + ret := []string{} + for _, f := range files { + ret = append(ret, f.Name()) + } + w.Header().Add("Content-Type", "application/json") + json.NewEncoder(w).Encode(ret) +} + +func deleteFileIfExists(w http.ResponseWriter, r *http.Request, dir string) { + fileName := strings.TrimPrefix(r.URL.Path, "/") + filePath := filepath.Join(dir, fileName) + _, err := os.Stat(filePath) + if err != nil { + http.Error(w, fmt.Sprintf("Unknown file %s", fileName), http.StatusNotFound) + return + } + err = os.Remove(filePath) + if err != nil { + http.Error(w, fmt.Sprintf("Failed to delete file %s: %v", fileName, err), http.StatusInternalServerError) + return + } +} diff --git a/selenium/base/fileserver/main_test.go b/selenium/base/fileserver/main_test.go new file mode 100644 index 0000000..465c4ac --- /dev/null +++ b/selenium/base/fileserver/main_test.go @@ -0,0 +1,58 @@ +package main + +import ( + . "github.com/aandryashin/matchers" + . "github.com/aandryashin/matchers/httpresp" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" +) + +var ( + dir string + srv *httptest.Server +) + +func init() { + dir, _ = ioutil.TempDir("", "fileserver") + srv = httptest.NewServer(mux(dir)) +} + +func withUrl(path string) string { + return srv.URL + path +} + +func TestDownloadAndRemoveFile(t *testing.T) { + tempFile, _ := ioutil.TempFile(dir, "fileserver") + ioutil.WriteFile(tempFile.Name(), []byte("test-data"), 0644) + tempFileName := filepath.Base(tempFile.Name()) + resp, err := http.Get(withUrl("/" + tempFileName)) + AssertThat(t, err, Is{nil}) + AssertThat(t, resp, Code{200}) + _, err = os.Stat(tempFile.Name()) + AssertThat(t, err, Is{nil}) + + rsp, err := http.Get(withUrl("/?json")) + AssertThat(t, err, Is{nil}) + AssertThat(t, rsp, Code{http.StatusOK}) + var files []string + AssertThat(t, rsp, IsJson{&files}) + AssertThat(t, files, EqualTo{[]string{tempFileName}}) + + req, _ := http.NewRequest(http.MethodDelete, withUrl("/" + tempFileName), nil) + resp, err = http.DefaultClient.Do(req) + AssertThat(t, err, Is{nil}) + AssertThat(t, resp, Code{200}) + _, err = os.Stat(tempFile.Name()) + AssertThat(t, err, Not{nil}) +} + +func TestRemoveMissingFile(t *testing.T) { + req, _ := http.NewRequest(http.MethodDelete, withUrl("/missing-file"), nil) + resp, err := http.DefaultClient.Do(req) + AssertThat(t, err, Is{nil}) + AssertThat(t, resp, Code{404}) +} diff --git a/selenium/base/fluxbox/aerokube b/selenium/base/fluxbox/aerokube new file mode 100644 index 0000000..b990e81 --- /dev/null +++ b/selenium/base/fluxbox/aerokube @@ -0,0 +1,175 @@ +############################################################################### +# +# name: aerokube (based on ubuntu_light) +# made: paultag +# date: 16-10-2010 +# http://pault.ag/ +# +############################################################## BACKGROUND ###### + +# background: flat +# background.color: #2c001e +# background.colorTo: #2c001e + +background: fullscreen +background.pixmap: /usr/share/images/fluxbox/aerokube.png + +############################################################## FONTS ########## + + +menu.frame.font: Ubuntu-10:bold +menu.title.font: Ubuntu-12:bold +toolbar.clock.font: Ubuntu-10:bold +toolbar.workspace.font: Ubuntu-12:bold +toolbar.iconbar.focused.font: Ubuntu-10:bold +toolbar.iconbar.unfocused.font: Ubuntu-10 +window.font: Ubuntu-10 + +############################################################## MENU ########### + +menu.bevelWidth: 1 + +#menu.itemHeight: 35 +#menu.titleHeight: 21 +menu.borderColor: #525252 +menu.borderWidth: 1 + +menu.bullet: Triangle +menu.bullet.position: Right +menu.frame.underlineColor: #ffffff + +menu.title: flat gradient rectangle +menu.title.justify: center +menu.title.color: #FFFFFF +menu.title.colorTo: #FFFFFF +menu.title.textColor: #333333 + +menu.frame: flat gradient crossdiagonal +menu.frame.justify: left +menu.frame.color: #FFFFFF +menu.frame.colorTo: #FFFFFF +menu.frame.textColor: #333333 +menu.frame.disableColor: #aea79f + +menu.hilite: flat gradient rectangle +menu.hilite.color: #aea79f +menu.hilite.colorTo: #aea79f +menu.hilite.textColor: #000000 + +############################################################## TOOLBAR ######## + +toolbar.bevelWidth: 0 + +toolbar.borderWidth: 1 +toolbar.borderColor: #aea79f + +toolbar.height: 20 + +toolbar.justify: center + +toolbar: flat gradient rectangle +toolbar.pixmap: +toolbar.color: #aea79f +toolbar.colorTo: #aea79f + +toolbar.clock: parentrelative +toolbar.clock.justify: center +toolbar.clock.color: # +toolbar.clock.colorTo: # +toolbar.clock.textColor: #333333 + +toolbar.workspace: parentrelative +toolbar.workspace.justify: Center +toolbar.workspace.color: # +toolbar.workspace.colorTo: # +toolbar.workspace.textColor: #333333 + +toolbar.button: parentrelative +toolbar.button.color: #333333 +toolbar.button.colorTo: #333333 +toolbar.button.picColor: #333333 +toolbar.button.pressed: parentrelative +toolbar.button.pressed.color: #aea79f +toolbar.button.pressed.colorTo: #aea79f +toolbar.button.pressed.picColor: #000000 + +toolbar.iconbar.borderWidth: 1 +toolbar.iconbar.borderColor: #333333 + +toolbar.iconbar.empty: parentrelative +toolbar.iconbar.empty.color: # +toolbar.iconbar.empty.colorTo: # + +toolbar.iconbar.focused.borderWidth: 1 +toolbar.iconbar.focused.borderColor: #333333 +toolbar.iconbar.focused: flat gradient rectangle +toolbar.iconbar.focused.color: #FFFFFF +toolbar.iconbar.focused.colorTo: #FFFFFF +toolbar.iconbar.focused.textColor: #333333 +toolbar.iconbar.focused.justify: center + +toolbar.iconbar.unfocused.borderWidth: 1 +toolbar.iconbar.unfocused.borderColor: #525252 +toolbar.iconbar.unfocused: flat gradient rectangle +toolbar.iconbar.unfocused.color: #aea79f +toolbar.iconbar.unfocused.colorTo: #aea79f +toolbar.iconbar.unfocused.textColor: #444444 +toolbar.iconbar.unfocused.justify: center + +############################################################## WINDOW ######### + +window.roundCorners: TopRight TopLeft +window.bevelWidth: 4 +window.shade: false +window.borderWidth: 1 +window.borderColor: #333333 + +window.justify: Center +window.title.height: 21 + +window.title.focus: flat gradient rectangle +window.title.focus.color: #000000 +window.title.focus.colorTo: #333333 +window.title.unfocus: flat gradient rectangle +window.title.unfocus.color: #111111 +window.title.unfocus.colorTo: #444444 + +window.label.focus: parentrelative +window.label.focus.color: # +window.label.focus.colorTo: # +window.label.focus.textColor: #FFFFFF +window.label.unfocus: parentrelative +window.label.unfocus.color: # +window.label.unfocus.colorTo: # +window.label.unfocus.textColor: #aea79f + +window.button.focus: parentrelative +window.button.focus.color: # +window.button.focus.colorTo: # +window.button.focus.picColor: #FFFFFF +window.button.unfocus: parentrelative +window.button.unfocus.Color: # +window.button.unfocus.ColorTo: # +window.button.unfocus.picColor: #888888 +window.button.pressed: parentrelative +window.button.pressed.color: # +window.button.pressed.colorTo: # +window.button.pressed.picColor: #000000 + +window.handle.focus: flat +window.handle.focus.color: #1f1f1f +window.handle.focus.colorTo: #1f1f1f +window.handle.unfocus: lat +window.handle.unfocus.color: #1f1f1f +window.handle.unfocus.colorTo: #1f1f1f +window.handleWidth: 2 + +window.grip.focus: flat +window.grip.focus.color: #525252 +window.grip.focus.colorTo: #525252 +window.grip.unfocus: flat +window.grip.unfocus.color: #1f1f1f +window.grip.unfocus.colorTo: #1f1f1f + +############################################################################### +# EOF \ No newline at end of file diff --git a/selenium/base/fluxbox/init b/selenium/base/fluxbox/init new file mode 100644 index 0000000..b41a387 --- /dev/null +++ b/selenium/base/fluxbox/init @@ -0,0 +1,7 @@ +session.menuFile: ~/.fluxbox/menu +session.keyFile: ~/.fluxbox/keys +session.styleFile: /usr/share/fluxbox/styles/aerokube +session.configVersion: 13 +session.screen0.strftimeFormat: %d %b, %a %02k:%M:%S +session.screen0.toolbar.visible: false +session.screen0.toolbar.tools: \ No newline at end of file diff --git a/selenium/base/xseld/go.mod b/selenium/base/xseld/go.mod new file mode 100644 index 0000000..7788b06 --- /dev/null +++ b/selenium/base/xseld/go.mod @@ -0,0 +1,3 @@ +module xseld + +go 1.17 diff --git a/selenium/base/xseld/main.go b/selenium/base/xseld/main.go new file mode 100644 index 0000000..37528fa --- /dev/null +++ b/selenium/base/xseld/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "io" + "log" + "net/http" + "os/exec" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + cmd := exec.Command("xsel", "-b") + switch r.Method { + case http.MethodGet: + cmd.Args = append(cmd.Args, "-o") + stdout, err := cmd.StdoutPipe() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + go io.Copy(w, stdout) + case http.MethodPost: + cmd.Args = append(cmd.Args, "-i") + stdin, err := cmd.StdinPipe() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + go func() { + defer stdin.Close() + io.Copy(stdin, r.Body) + }() + default: + http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) + return + } + err := cmd.Run() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + }) + log.Fatal(http.ListenAndServe(":9090", nil)) +} diff --git a/selenium/external-host/Dockerfile b/selenium/external-host/Dockerfile new file mode 100644 index 0000000..6bc4ef7 --- /dev/null +++ b/selenium/external-host/Dockerfile @@ -0,0 +1,28 @@ +FROM golang:1.17 as go + +COPY choose /choose + +COPY rproxy /rproxy + +RUN \ + apt-get update && \ + apt-get install -y upx-ucl && \ + cd /choose && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /choose/choose && \ + cd /rproxy && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /rproxy/rproxy + +FROM ubuntu:18.04 + +COPY --from=go /choose/choose /usr/local/bin/ +COPY --from=go /rproxy/rproxy /usr/local/bin/ + +RUN \ + apt update && \ + apt -y install xvfb x11-utils x11vnc tigervnc-common tigervnc-viewer + +COPY entrypoint.sh / +ENTRYPOINT ["/entrypoint.sh"] + diff --git a/selenium/external-host/README.md b/selenium/external-host/README.md new file mode 100644 index 0000000..28c03cf --- /dev/null +++ b/selenium/external-host/README.md @@ -0,0 +1,16 @@ +#browsers.json + +``` + "MicrosoftEdge": { + "default": "77", + "versions": { + "77": { + "image": "selenoid/external-host:1.0.0", + "port": "4444", + "path": "/", + "env": ["URLS=[\"http://172.17.0.1:4444/\"]","VNC_PASSWORD=longpassword","SCREEN_RESOLUTION=1921x1080x24"] + } + } + } + +``` diff --git a/selenium/external-host/choose/main.go b/selenium/external-host/choose/main.go new file mode 100644 index 0000000..36db5b9 --- /dev/null +++ b/selenium/external-host/choose/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "os" + "time" + "fmt" + "encoding/json" + "math/rand" +) + +var ( + s rand.Source + r *rand.Rand +) + +func init() { + s = rand.NewSource(time.Now().Unix()) + r = rand.New(s) +} + +func main() { + var hosts []string + if err := json.Unmarshal([]byte(os.Getenv("URLS")), &hosts); err != nil { + fmt.Printf("unmarshal json: %v", err) + os.Exit(1) + } + if l := len(hosts); l > 0 { + fmt.Println(hosts[r.Intn(l)]) + } +} diff --git a/selenium/external-host/entrypoint.sh b/selenium/external-host/entrypoint.sh new file mode 100755 index 0000000..b1b7d35 --- /dev/null +++ b/selenium/external-host/entrypoint.sh @@ -0,0 +1,51 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +URLS=${URLS:-'["http://172.17.0.1:4444/"]'} +VNC_PASSWORD=${VNC_PASSWORD:-"password"} +export URLS +export VNC_PASSWORD +export DISPLAY=":$DISPLAY_NUM" + +clean() { + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi + if [ -n "$RPROXY_PID" ]; then + kill -TERM "$RPROXY_PID" + fi + +} + +trap clean SIGINT SIGTERM + +URL=$(choose $URL) +HOST=$(echo $URL | sed -e 's@\(.*\)://@@' -e 's@[:/]\(.*\)$@@') + +/bin/bash -c 'echo -e "$VNC_PASSWORD\n$VNC_PASSWORD\nn\n" | vncpasswd file.passwd'>/dev/null + +xvfb-run -l -n $DISPLAY_NUM -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" \ + vncviewer passwd=file.passwd $HOST & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + xdpyinfo -display $DISPLAY >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting xvfb... + sleep 1 + fi +done + +x11vnc -display $DISPLAY -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & +X11VNC_PID=$! + +rproxy $URL & +RPROXY_PID=$! + +wait + diff --git a/selenium/external-host/rproxy/main.go b/selenium/external-host/rproxy/main.go new file mode 100644 index 0000000..d89b162 --- /dev/null +++ b/selenium/external-host/rproxy/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "log" + "net/http" + "net/http/httputil" + "net/url" + "os" +) + +func main() { + u, err := url.Parse(os.Args[1]) + if err != nil { + log.Fatalf("parse url: %v", err) + } + log.Fatal(http.ListenAndServe(":4444", httputil.NewSingleHostReverseProxy(u))) +} diff --git a/selenium/opera_presto/Dockerfile b/selenium/opera_presto/Dockerfile new file mode 100644 index 0000000..945b657 --- /dev/null +++ b/selenium/opera_presto/Dockerfile @@ -0,0 +1,16 @@ +FROM browsers/base:7.3.6 + +RUN \ + curl -s https://deb.opera.com/archive.key | apt-key add - && \ + echo 'deb https://deb.opera.com/opera/ stable non-free' >> /etc/apt/sources.list.d/opera.list && \ + apt-get update && \ + apt-get -y install opera=12.16.1860 openjdk-8-jre-headless && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* + +COPY selenium-server-standalone.jar /usr/share/selenium/ +COPY entrypoint.sh / + +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/selenium/opera_presto/entrypoint.sh b/selenium/opera_presto/entrypoint.sh new file mode 100755 index 0000000..f60e041 --- /dev/null +++ b/selenium/opera_presto/entrypoint.sh @@ -0,0 +1,54 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +ENABLE_WINDOW_MANAGER=${ENABLE_WINDOW_MANAGER:-""} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$SELENIUM_PID" ]; then + kill -TERM "$SELENIUM_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /tmp/fluxbox.log 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /tmp/x11vnc.log & + X11VNC_PID=$! +fi + +/usr/bin/java -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar /usr/share/selenium/selenium-server-standalone.jar -port 4444 -browserTimeout 120 & +SELENIUM_PID=$! + +wait diff --git a/selenium/phantomjs/Dockerfile b/selenium/phantomjs/Dockerfile new file mode 100644 index 0000000..e688712 --- /dev/null +++ b/selenium/phantomjs/Dockerfile @@ -0,0 +1,3 @@ +FROM wernight/phantomjs:2.1.1 +EXPOSE 4444 +CMD ["/usr/local/bin/phantomjs", "--webdriver=4444"] diff --git a/selenium/util/README.md b/selenium/util/README.md new file mode 100644 index 0000000..c054be5 --- /dev/null +++ b/selenium/util/README.md @@ -0,0 +1,10 @@ +# Rebuilding Debian Packages + +1. Download package from APT-repository: +``` +$ apt-get download google-chrome-stable=48.0.2564.109-1+suffix0 +``` +2. Rebuild package to new owner using script: +``` +$ rebuild-deb.sh -f google-chrome-stable=48.0.2564.109-1+suffix0_amd64.deb -r 'suffix0' -a 'aerokube0' +``` \ No newline at end of file diff --git a/selenium/util/rebuild-deb.sh b/selenium/util/rebuild-deb.sh new file mode 100755 index 0000000..fb06b64 --- /dev/null +++ b/selenium/util/rebuild-deb.sh @@ -0,0 +1,94 @@ +#!/bin/bash +set -e + +usage() +{ +cat << EOF +usage: $0 options + +OPTIONS: + -h Show this message + -f Filename + -r Remove version postfix + -a Add version postfix +EOF +} + +filename='' +remove_postfix='' +add_postfix='' + +while getopts 'f:r:a:' OPTION +do + case $OPTION in + h) + usage + exit 1 + ;; + f) + filename=$OPTARG + ;; + r) + remove_postfix=$OPTARG + ;; + a) + add_postfix=$OPTARG + ;; + ?) + usage + exit + ;; + esac +done + +if [ -z "$filename" ]; then + usage + exit 1 +fi +set -x + +cp "$filename" . +spackage=$(echo "$filename" | awk -F '/' '{print $NF}') +package=$(echo "$spackage" | awk -F '_' '{print $1}') +version=$(echo "$spackage" | awk -F '_' '{print $2}') +rm -Rf "$package" control changelog + +# Set variables +export DH_ALWAYS_EXCLUDE="CVS:.svn:.git" + +# Extract package content +dpkg-deb -x $spackage $package/ + +# Extract package control +dpkg-deb -e $spackage $package/DEBIAN + +# Extract package changelog +changelog=$(find $package/usr/share/doc -name 'changelog*.gz' 2>/dev/null| head -n 1) +if [ -n "$changelog" -a -f "$changelog" ]; then + rm -f "$changelog" +fi +old_version=$version +if [ -n "$remove_postfix" ]; then + version=$(echo $version | sed -e "s|+$remove_postfix||g") + old_version=$version"+"$remove_postfix +fi +new_version=$version +if [ -n "$add_postfix" ]; then + new_version=$new_version"+"$add_postfix +fi +dch --create --force-distribution --distribution unstable --package "$package" --newversion "$new_version" -c changelog 'Package rebuilt' + +# Fix control +section=$(awk '/Section:/ {print $NF}' $package/DEBIAN/control 2>/dev/null || echo 'misc') +priority=$(awk '/Priority:/ {print $NF}' $package/DEBIAN/control 2>/dev/null || echo 'extra') +echo "$(echo $spackage | sed "s/$old_version/$new_version/") $section $priority" > files +echo "Source: $package" > control +grep -iv "Source:" $package/DEBIAN/control >> control +cp control $package/DEBIAN/control + +# Build package +sed -i "s/$old_version/$new_version/g" $package/DEBIAN/control +dpkg-deb -b $package/ ./ + +# Remove source package +rm -f "./$spackage" diff --git a/selenium/video/APKBUILD b/selenium/video/APKBUILD new file mode 100644 index 0000000..e126741 --- /dev/null +++ b/selenium/video/APKBUILD @@ -0,0 +1,76 @@ +# Contributor: Anton Dzyk +# Maintainer: Ivan Krutov +pkgname=ffmpeg-x11grab +pkgsource=ffmpeg +pkgver=4.3 +pkgrel=1 +pkgdesc="FFMPEG version optimized for x11grab to x264" +url="https://ffmpeg.org" +arch="all" +license="LGPL-2.1-or-later GPL-2.0-or-later" +makedepends="gnutls-dev lame-dev libvorbis-dev xvidcore-dev zlib-dev libvdpau-dev + imlib2-dev x264-dev libtheora-dev coreutils bzip2-dev perl-dev libvpx-dev + libvpx-dev sdl2-dev libxfixes-dev libva-dev v4l-utils-dev yasm opus-dev libass-dev pulseaudio-dev" +source="https://ffmpeg.org/releases/ffmpeg-$pkgver.tar.xz + 0001-libavutil-clean-up-unused-FF_SYMVER-macro.patch + " +builddir="$srcdir/$pkgsource-$pkgver" + +build() { + local _dbg="--disable-debug" + local _asm="" + [ -n "$DEBUG" ] && _dbg="--enable-debug" + + case "$CARCH" in + x86 | arm*) _asm="--disable-asm" ;; + esac + + cd "$builddir" + ./configure \ + --prefix=/usr \ + --enable-avfilter \ + --enable-gpl \ + --enable-libx264 \ + --enable-libpulse \ + --enable-static \ + --enable-small \ + --disable-ffplay \ + --disable-ffprobe \ + --disable-doc \ + --disable-htmlpages \ + --disable-manpages \ + --disable-podpages \ + --disable-txtpages \ + --disable-w32threads \ + --disable-alsa \ + --disable-audiotoolbox \ + --disable-cuda \ + --disable-cuvid \ + --disable-d3d11va \ + --disable-dxva2 \ + --disable-nvenc \ + --disable-vaapi \ + --disable-vdpau \ + --disable-videotoolbox \ + --disable-librtmp \ + --disable-devices \ + --enable-indev=xcbgrab \ + --enable-indev=pulse \ + $_asm $_dbg + make +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install +} + +libs() { + pkgdesc="Libraries for ffmpeg" + replaces="ffmpeg" + mkdir -p "$subpkgdir"/usr + mv "$pkgdir"/usr/lib "$subpkgdir"/usr +} + +sha512sums="f031eb6c4423887af323ab7d1f431234d4e30993a52db45dccf427b41eb442a3bd020dcbc13e83cbf813fad0f36c849cb651203570148387c864507aa19f313a ffmpeg-4.3.tar.xz +1047a23eda51b576ac200d5106a1cd318d1d5291643b3a69e025c0a7b6f3dbc9f6eb0e1e6faa231b7e38c8dd4e49a54f7431f87a93664da35825cc2e9e8aedf4 0001-libavutil-clean-up-unused-FF_SYMVER-macro.patch" diff --git a/selenium/video/Dockerfile b/selenium/video/Dockerfile new file mode 100644 index 0000000..920570a --- /dev/null +++ b/selenium/video/Dockerfile @@ -0,0 +1,21 @@ +FROM alpine:3.12 + +RUN apk add -U alpine-sdk && adduser -g "" -D -G abuild selenoid +USER selenoid +RUN git clone git://git.alpinelinux.org/aports /home/selenoid/aports +ADD APKBUILD /home/selenoid/aports/community/ffmpeg/ +RUN cd /home/selenoid/aports/community/ffmpeg/ && \ + abuild checksum && \ + abuild unpack && \ + abuild deps && \ + abuild build +USER root + +FROM alpine:3.12 + +RUN apk add -U x264-libs sdl2 libxcb libbz2 xset pulseaudio-utils && \ + rm -rf /var/cache/apk/* +COPY --from=0 /home/selenoid/aports/community/ffmpeg/src/ffmpeg-4.3/ffmpeg /usr/bin/ffmpeg + +COPY entrypoint.sh / +ENTRYPOINT ["/entrypoint.sh"] diff --git a/selenium/video/entrypoint.sh b/selenium/video/entrypoint.sh new file mode 100755 index 0000000..e07ad60 --- /dev/null +++ b/selenium/video/entrypoint.sh @@ -0,0 +1,42 @@ +#!/bin/sh +VIDEO_SIZE=${VIDEO_SIZE:-"1920x1080"} +BROWSER_CONTAINER_NAME=${BROWSER_CONTAINER_NAME:-"browser"} +DISPLAY=${DISPLAY:-"99"} +FILE_NAME=${FILE_NAME:-"video.mp4"} +FRAME_RATE=${FRAME_RATE:-"12"} +CODEC=${CODEC:-"libx264"} +PRESET=${PRESET:-""} +if [ "$CODEC" == "libx264" -a -n "$PRESET" ]; then + PRESET="-preset $PRESET" +fi +INPUT_OPTIONS=${INPUT_OPTIONS:-""} +HIDE_CURSOR=${HIDE_CURSOR:-""} +if [ -n "$HIDE_CURSOR" ]; then + INPUT_OPTIONS="$INPUT_OPTIONS -draw_mouse 0" +fi + +retcode=1 +max_attempts=300 +attempts=0 +echo 'Waiting for display to open...' +until [ $retcode -eq 0 -o $attempts -eq $max_attempts ]; do + xset -display ${BROWSER_CONTAINER_NAME}:${DISPLAY} b off > /dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo 'Sleeping before next attempt...' + sleep 0.1 + fi + attempts=$((attempts+1)) +done + +mkdir -p ~/.config/pulse + +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/.config/pulse/cookie + +export PULSE_SERVER=${BROWSER_CONTAINER_NAME} + +if pactl info >/dev/null 2>&1; then + exec ffmpeg -f pulse -i default -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} ${INPUT_OPTIONS} -i ${BROWSER_CONTAINER_NAME}:${DISPLAY} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p -filter:v "pad=ceil(iw/2)*2:ceil(ih/2)*2" "/data/$FILE_NAME" +else + exec ffmpeg -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} ${INPUT_OPTIONS} -i ${BROWSER_CONTAINER_NAME}:${DISPLAY} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p -filter:v "pad=ceil(iw/2)*2:ceil(ih/2)*2" "/data/$FILE_NAME" +fi diff --git a/static/chrome/Dockerfile b/static/chrome/Dockerfile new file mode 100644 index 0000000..e4e4337 --- /dev/null +++ b/static/chrome/Dockerfile @@ -0,0 +1,25 @@ +ARG VERSION +FROM golang:1.17 as go + +COPY devtools /devtools + +RUN \ + apt-get update && \ + apt-get install -y upx-ucl && \ + cd /devtools && \ + go test -race && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /devtools/devtools + +FROM selenoid/dev_chrome:$VERSION + +ENV DBUS_SESSION_BUS_ADDRESS=/dev/null +COPY --from=go /devtools/devtools /usr/bin/ +COPY chromedriver /usr/bin/ +COPY entrypoint.sh / + +RUN chmod +x /usr/bin/chromedriver +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/chrome/apt/Dockerfile b/static/chrome/apt/Dockerfile new file mode 100644 index 0000000..32b91c0 --- /dev/null +++ b/static/chrome/apt/Dockerfile @@ -0,0 +1,18 @@ +FROM browsers/base:7.3.6 + +ARG VERSION +ARG PACKAGE=google-chrome-stable +ARG INSTALL_DIR=chrome + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + curl -s https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ + echo 'deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main' > /etc/apt/sources.list.d/google.list && \ + apt-get update && \ + apt-get -y --no-install-recommends install iproute2 $PACKAGE=$VERSION && \ + sed -i -e 's@exec -a "$0" "$HERE/chrome"@& --no-sandbox --disable-gpu@' /opt/google/$INSTALL_DIR/google-chrome && \ + chown root:root /opt/google/$INSTALL_DIR/chrome-sandbox && \ + chmod 4755 /opt/google/$INSTALL_DIR/chrome-sandbox && \ + google-chrome --version && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/chrome/devtools/.gitignore b/static/chrome/devtools/.gitignore new file mode 100644 index 0000000..4ca5bed --- /dev/null +++ b/static/chrome/devtools/.gitignore @@ -0,0 +1 @@ +devtools \ No newline at end of file diff --git a/static/chrome/devtools/devtools.go b/static/chrome/devtools/devtools.go new file mode 100644 index 0000000..ce53f63 --- /dev/null +++ b/static/chrome/devtools/devtools.go @@ -0,0 +1,187 @@ +package main + +import ( + "context" + "errors" + "fmt" + "github.com/mafredri/cdp/devtool" + "io/ioutil" + "log" + "net/http" + "net/http/httputil" + "net/url" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" +) + +const ( + devtoolsBaseDir = "/tmp" + slash = "/" +) + +var ( + defaultDevtoolsHost = "127.0.0.1:9222" +) + +func root() http.Handler { + mux := http.NewServeMux() + mux.HandleFunc("/browser", browser) + mux.HandleFunc("/json/protocol", protocol) + mux.HandleFunc("/page", page) + mux.HandleFunc("/page/", page) + mux.HandleFunc("/", browser) + return mux +} + +func browser(w http.ResponseWriter, r *http.Request) { + u, err := getBrowserWebSocketUrl() + if err != nil { + log.Printf("[BROWSER_URL_ERROR] [%v]", err) + return + } + log.Printf("[BROWSER] [%s]", u.String()) + proxyWebSocket(w, r, u) +} + +func proxyWebSocket(w http.ResponseWriter, r *http.Request, u *url.URL) { + u.Scheme = "http" + (&httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.Host = "localhost" + r.URL = u + }, + }).ServeHTTP(w, r) +} + +func page(w http.ResponseWriter, r *http.Request) { + fragments := strings.Split(r.URL.Path, slash) + targetId := "" + if len(fragments) == 3 { + targetId = fragments[2] + } + u, err := getPageWebSocketUrl(targetId) + if err != nil { + log.Printf("[PAGE_URL_ERROR] [%v]", err) + return + } + log.Printf("[PAGE] [%s]", u.String()) + proxyWebSocket(w, r, u) +} + +func protocol(w http.ResponseWriter, r *http.Request) { + h, err := devtoolsHost() + if err != nil { + log.Printf("[DEVTOOLS_HOST_ERROR] [%v]", err) + http.Error(w, fmt.Sprintf("Failed to detect devtools host: %v", err), http.StatusInternalServerError) + return + } + u := &url.URL{ + Host: h, + Scheme: "http", + Path: "/json/protocol", + } + log.Printf("[PROTOCOL] [%s]", u.String()) + (&httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.Host = "localhost" + r.URL = u + }, + }).ServeHTTP(w, r) +} + +func getBrowserWebSocketUrl() (*url.URL, error) { + ctx := context.Background() + h, err := devtoolsHost() + if err != nil { + return nil, fmt.Errorf("failed to detect devtools port: %v", err) + } + dt := devtool.New(fmt.Sprintf("http://%s", h)) + ver, err := dt.Version(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get browser websocket url: %v", err) + } + + wsUrl, err := url.Parse(ver.WebSocketDebuggerURL) + if err == nil { + return wsUrl, nil + } + return nil, errors.New("browser websocket URL information not found") +} + +func getPageWebSocketUrl(targetId string) (*url.URL, error) { + ctx := context.Background() + h, err := devtoolsHost() + if err != nil { + return nil, fmt.Errorf("failed to detect devtools port: %v", err) + } + dt := devtool.New(fmt.Sprintf("http://%s", h)) + targets, err := dt.List(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list targets: %v", err) + } + for _, t := range targets { + if (targetId == "" && t.Type == devtool.Page) || targetId == t.ID { + wsUrl, err := url.Parse(t.WebSocketDebuggerURL) + if err != nil { + return nil, fmt.Errorf("invalid websocket URL for matched target %s: %v", t.ID, err) + } + return wsUrl, nil + } + } + return nil, errors.New("no matching target found") +} + +func devtoolsHost() (string, error) { + if android { + return androidDevtoolsHost() + } + return detectDevtoolsHost(devtoolsBaseDir), nil +} + +func androidDevtoolsHost() (string, error) { + const androidDevtoolsPort = 9333 + cmd := exec.Command("adb", "forward", fmt.Sprintf("tcp:%d", androidDevtoolsPort), "localabstract:chrome_devtools_remote") + err := cmd.Run() + if err != nil { + return "", fmt.Errorf("failed to forward devtools port: %v", err) + } + return fmt.Sprintf("localhost:%d", androidDevtoolsPort), nil +} + +func detectDevtoolsHost(baseDir string) string { + var candidates []string + for _, glob := range []string{".com.google.Chrome*", ".org.chromium.Chromium*"} { + cds, err := filepath.Glob(filepath.Join(baseDir, glob)) + if err == nil { + candidates = append(candidates, cds...) + } + + } + for _, c := range candidates { + f, err := os.Stat(c) + if err != nil { + continue + } + if !f.IsDir() { + continue + } + portFile := filepath.Join(c, "DevToolsActivePort") + data, err := ioutil.ReadFile(portFile) + if err != nil { + continue + } + lines := strings.Split(string(data), "\n") + if len(lines) == 0 { + continue + } + port, err := strconv.Atoi(lines[0]) + if err != nil { + continue + } + return fmt.Sprintf("127.0.0.1:%d", port) + } + return defaultDevtoolsHost +} diff --git a/static/chrome/devtools/devtools_test.go b/static/chrome/devtools/devtools_test.go new file mode 100644 index 0000000..6105e7d --- /dev/null +++ b/static/chrome/devtools/devtools_test.go @@ -0,0 +1,176 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + . "github.com/aandryashin/matchers" + . "github.com/aandryashin/matchers/httpresp" + "github.com/gorilla/websocket" + "github.com/mafredri/cdp" + "github.com/mafredri/cdp/protocol/target" + "github.com/mafredri/cdp/rpcc" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + "time" +) + +var ( + srv *httptest.Server + devtoolsSrv *httptest.Server +) + +func init() { + srv = httptest.NewServer(root()) + listen = srv.Listener.Addr().String() + devtoolsSrv = httptest.NewServer(mockDevtoolsMux()) + defaultDevtoolsHost = devtoolsSrv.Listener.Addr().String() +} + +func mockDevtoolsMux() http.Handler { + mux := http.NewServeMux() + version := func(w http.ResponseWriter, _ *http.Request) { + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(fmt.Sprintf(`{ + "Browser": "Chrome/72.0.3601.0", + "Protocol-Version": "1.3", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3601.0 Safari/537.36", + "V8-Version": "7.2.233", + "WebKit-Version": "537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)", + "webSocketDebuggerUrl": "ws://%s/devtools/browser/b0b8a4fb-bb17-4359-9533-a8d9f3908bd8" + }`, defaultDevtoolsHost))) + } + mux.HandleFunc("/json/version", version) + listTargets := func(w http.ResponseWriter, _ *http.Request) { + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(fmt.Sprintf(`[ { + "description": "", + "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/one", + "id": "one", + "title": "Aerokube", + "type": "page", + "url": "https://www.aerokube.com/", + "webSocketDebuggerUrl": "ws://%s/devtools/page/one" +}, { + "description": "", + "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/two", + "id": "two", + "title": "Aerokube Selenoid", + "type": "page", + "url": "https://selenoid.aerokube.com/", + "webSocketDebuggerUrl": "ws://%s/devtools/page/two" +} ]`, defaultDevtoolsHost, defaultDevtoolsHost))) + + } + mux.HandleFunc("/json/list", listTargets) + mux.HandleFunc("/json", listTargets) + + mux.HandleFunc("/json/protocol", func(w http.ResponseWriter, _ *http.Request) { + w.Header().Add("Content-Type", "application/json") + w.Write([]byte("{}")) + }) + + upgrader := websocket.Upgrader{ + CheckOrigin: func(_ *http.Request) bool { + return true + }, + } + + devtoolsEcho := func(w http.ResponseWriter, r *http.Request) { + //Echo request ID but omit Method + c, err := upgrader.Upgrade(w, r, nil) + if err != nil { + panic(err) + } + defer c.Close() + for { + mt, message, err := c.ReadMessage() + if err != nil { + break + } + var req rpcc.Request + err = json.Unmarshal(message, &req) + if err != nil { + panic(err) + } + resp := rpcc.Response{ + ID: req.ID, + } + if req.Method == "Target.getTargets" { + result := target.GetTargetsReply{ + TargetInfos: []target.Info{ + {TargetID: "one", Type: "page"}, + {TargetID: "two", Type: "page"}, + }, + } + resBytes, _ := json.Marshal(result) + resp.Result = json.RawMessage(resBytes) + } + output, err := json.Marshal(resp) + if err != nil { + panic(err) + } + err = c.WriteMessage(mt, output) + if err != nil { + break + } + } + } + + mux.HandleFunc("/devtools/browser/", devtoolsEcho) + mux.HandleFunc("/devtools/page/", devtoolsEcho) + return mux +} + +func TestProtocol(t *testing.T) { + u := fmt.Sprintf("http://%s/json/protocol", srv.Listener.Addr().String()) + resp, err := http.Get(u) + AssertThat(t, err, Is{nil}) + AssertThat(t, resp, Code{200}) +} + +func TestDevtools(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) + defer cancel() + + browserWs := fmt.Sprintf("ws://%s/", srv.Listener.Addr().String()) + browserConn, err := rpcc.DialContext(ctx, browserWs) + AssertThat(t, err, Is{nil}) + defer browserConn.Close() + + browserClient := cdp.NewClient(browserConn) + targets, err := browserClient.Target.GetTargets(ctx) + AssertThat(t, err, Is{nil}) + AssertThat(t, len(targets.TargetInfos), EqualTo{2}) + + defaultPageWs := fmt.Sprintf("ws://%s/page", srv.Listener.Addr().String()) + defaultPageConn, err := rpcc.DialContext(ctx, defaultPageWs) + AssertThat(t, err, Is{nil}) + defer defaultPageConn.Close() + defaultPageClient := cdp.NewClient(defaultPageConn) + err = defaultPageClient.Page.Enable(ctx) + AssertThat(t, err, Is{nil}) + + selectedPageWs := fmt.Sprintf("ws://%s/page/%s", srv.Listener.Addr().String(), targets.TargetInfos[1].TargetID) + selectedPageConn, err := rpcc.DialContext(ctx, selectedPageWs) + AssertThat(t, err, Is{nil}) + defer selectedPageConn.Close() + selectedPageClient := cdp.NewClient(selectedPageConn) + err = selectedPageClient.Page.Enable(ctx) + AssertThat(t, err, Is{nil}) +} + +func TestDetectDevtoolsHost(t *testing.T) { + name, _ := ioutil.TempDir("", "devtools") + defer os.RemoveAll(name) + profilePath := filepath.Join(name, ".org.chromium.Chromium.deadbee") + os.MkdirAll(profilePath, os.ModePerm) + portFile := filepath.Join(profilePath, "DevToolsActivePort") + ioutil.WriteFile(portFile, []byte("12345\n/devtools/browser/6f37c7fe-a0a6-4346-a6e2-80c5da0687f0"), 0644) + + AssertThat(t, detectDevtoolsHost(name), EqualTo{"127.0.0.1:12345"}) +} diff --git a/static/chrome/devtools/go.mod b/static/chrome/devtools/go.mod new file mode 100644 index 0000000..f2d1f5a --- /dev/null +++ b/static/chrome/devtools/go.mod @@ -0,0 +1,12 @@ +module github.com/aerokube/devtools + +go 1.14 + +require ( + github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e + github.com/google/go-cmp v0.2.0 // indirect + github.com/gorilla/websocket v1.4.2 + github.com/mafredri/cdp v0.23.4 + golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0 // indirect + golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect +) diff --git a/static/chrome/devtools/go.sum b/static/chrome/devtools/go.sum new file mode 100644 index 0000000..96bacd4 --- /dev/null +++ b/static/chrome/devtools/go.sum @@ -0,0 +1,12 @@ +github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e h1:ogUKYFNcdYUIBSLibE4+EjbTJazoHr5JsWWx21Lpn8c= +github.com/aandryashin/matchers v0.0.0-20161126170413-435295ea180e/go.mod h1:cbmYNkm9xeQlNoWEPtOUcvNok2gSD7ErMnYkRW+eHi8= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/mafredri/cdp v0.23.4 h1:ffp4qq6slfCL4rFWBDeRHapkLE776gER4tX5Z3LS8CY= +github.com/mafredri/cdp v0.23.4/go.mod h1:hgdiA0yp1uqhSaDOHJWPgXpMbh+LAfUdD9vbN2AM8gE= +golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0 h1:1DW40AJQ7AP4nY6ORUGUdkpXyEC9W2GAXcOPaMZK0K8= +golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/static/chrome/devtools/main.go b/static/chrome/devtools/main.go new file mode 100644 index 0000000..6a0bced --- /dev/null +++ b/static/chrome/devtools/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "flag" + "log" + "net/http" +) + +var ( + listen string + android bool +) + +func init() { + flag.StringVar(&listen, "listen", ":7070", "Network address to accept connections") + flag.BoolVar(&android, "android", false, "Whether we need to forward Android Emulator devtools port") +} + +func main() { + flag.Parse() + log.Printf("[INIT] [Listening on %s]", listen) + log.Fatal(http.ListenAndServe(listen, root())) +} diff --git a/static/chrome/entrypoint.sh b/static/chrome/entrypoint.sh new file mode 100755 index 0000000..181bc05 --- /dev/null +++ b/static/chrome/entrypoint.sh @@ -0,0 +1,93 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +VERBOSE=${VERBOSE:-""} +DRIVER_ARGS=${DRIVER_ARGS:-""} +if [ -n "$VERBOSE" ]; then + DRIVER_ARGS="$DRIVER_ARGS --verbose" +fi + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$DRIVER_PID" ]; then + kill -TERM "$DRIVER_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi + if [ -n "$DEVTOOLS_PID" ]; then + kill -TERM "$DEVTOOLS_PID" + fi + if [ -n "$PULSE_PID" ]; then + kill -TERM "$PULSE_PID" + fi +} + +trap clean SIGINT SIGTERM + +if env | grep -q ROOT_CA_; then + mkdir -p $HOME/.pki/nssdb + certutil -N --empty-password -d sql:$HOME/.pki/nssdb + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/cert.pem + certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb + if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then + PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'} + openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS} + pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS} + rm /tmp/key.p12 + fi + rm /tmp/cert.pem + done +fi + +/usr/bin/fileserver & +FILESERVER_PID=$! + +/usr/bin/devtools & +DEVTOOLS_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +while ip addr | grep inet | grep -q tentative > /dev/null; do sleep 0.1; done + +mkdir -p ~/pulse/.config/pulse +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie +HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1 +HOME=$HOME/pulse pactl load-module module-native-protocol-tcp +PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g') + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/chromedriver --port=4444 --allowed-ips='' --allowed-origins='*' ${DRIVER_ARGS} & +DRIVER_PID=$! + +wait diff --git a/static/chrome/local/Dockerfile b/static/chrome/local/Dockerfile new file mode 100644 index 0000000..0068d3c --- /dev/null +++ b/static/chrome/local/Dockerfile @@ -0,0 +1,62 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=noop +ARG PACKAGE=google-chrome-stable +ARG INSTALL_DIR=chrome + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install gconf-service \ + libasound2 \ + libatk1.0-0 \ + libc6 \ + libcairo2 \ + libcups2 \ + libdbus-1-3 \ + libexpat1 \ + libfontconfig1 \ + libfreetype6 \ + libgcc1 \ + libgconf-2-4 \ + libgdk-pixbuf2.0-0 \ + libglib2.0-0 \ + libgtk2.0-0 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libpango1.0-0 \ + libstdc++6 \ + libx11-6 \ + libx11-xcb1 \ + libxcb1 \ + libxcomposite1 \ + libxcursor1 \ + libxdamage1 \ + libxext6 \ + libxfixes3 \ + libxi6 \ + libxrandr2 \ + libxrender1 \ + libxss1 \ + libxtst6 \ + ca-certificates \ + fonts-liberation \ + libappindicator3-1 \ + libnss3 \ + lsb-base \ + xdg-utils \ + libcurl4 \ + iproute2 \ + curl && \ + curl -O http://host.docker.internal:8080/google-chrome.deb && \ + apt-get -y purge curl && \ + dpkg -i google-chrome.deb && \ + sed -i -e 's@exec -a "$0" "$HERE/chrome"@& --no-sandbox --disable-gpu@' /opt/google/$INSTALL_DIR/$PACKAGE && \ + rm google-chrome.deb && \ + chown root:root /opt/google/$INSTALL_DIR/chrome-sandbox && \ + chmod 4755 /opt/google/$INSTALL_DIR/chrome-sandbox && \ + google-chrome --version && \ + rm -Rf /tmp/* && \ + rm -Rf /var/lib/apt/lists/* diff --git a/static/edge/Dockerfile b/static/edge/Dockerfile new file mode 100644 index 0000000..22df0ab --- /dev/null +++ b/static/edge/Dockerfile @@ -0,0 +1,12 @@ +ARG VERSION +FROM selenoid/dev_edge:$VERSION + +ENV DBUS_SESSION_BUS_ADDRESS=/dev/null +COPY msedgedriver /usr/bin/ +COPY entrypoint.sh / + +RUN chmod +x /usr/bin/msedgedriver +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/edge/apt/Dockerfile b/static/edge/apt/Dockerfile new file mode 100644 index 0000000..ccde8a7 --- /dev/null +++ b/static/edge/apt/Dockerfile @@ -0,0 +1,21 @@ +FROM browsers/base:7.3.6 + +ARG VERSION +ARG PACKAGE=microsoft-edge-stable +ARG INSTALL_DIR=msedge + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ + echo 'deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main' > /etc/apt/sources.list.d/microsoft-edge.list && \ + apt-get update && \ + apt-get -y --no-install-recommends install $PACKAGE=$VERSION && \ + ( \ + sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/$PACKAGE || \ + sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/microsoft-edge \ + ) && \ + chown root:root /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \ + chmod 4755 /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \ + microsoft-edge --version && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/edge/entrypoint.sh b/static/edge/entrypoint.sh new file mode 100755 index 0000000..596b5fa --- /dev/null +++ b/static/edge/entrypoint.sh @@ -0,0 +1,86 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +VERBOSE=${VERBOSE:-""} +DRIVER_ARGS=${DRIVER_ARGS:-""} +if [ -n "$VERBOSE" ]; then + DRIVER_ARGS="$DRIVER_ARGS --verbose" +fi + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$PULSE_PID" ]; then + kill -TERM "$PULSE_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$DRIVER_PID" ]; then + kill -TERM "$DRIVER_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +if env | grep -q ROOT_CA_; then + mkdir -p $HOME/.pki/nssdb + certutil -N --empty-password -d sql:$HOME/.pki/nssdb + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/cert.pem + certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb + if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then + PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'} + openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS} + pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS} + rm /tmp/key.p12 + fi + rm /tmp/cert.pem + done +fi + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +mkdir -p ~/pulse/.config/pulse +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie +HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1 +HOME=$HOME/pulse pactl load-module module-native-protocol-tcp +PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g') + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/msedgedriver --port=4444 --allowed-ips='' ${DRIVER_ARGS} & +DRIVER_PID=$! + +wait + diff --git a/static/edge/local/Dockerfile b/static/edge/local/Dockerfile new file mode 100644 index 0000000..6e0d19d --- /dev/null +++ b/static/edge/local/Dockerfile @@ -0,0 +1,47 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=noop +ARG PACKAGE=microsoft-edge-stable +ARG INSTALL_DIR=msedge + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install libatk-bridge2.0-0 \ + libatomic1 \ + libatspi2.0-0 \ + libcairo-gobject2 \ + libcolord2 \ + libepoxy0 \ + libgbm1 \ + libgtk-3-0 \ + libgtk-3-common \ + liblcms2-2 \ + librest-0.7-0 \ + libsoup-gnome2.4-1 \ + libwayland-client0 \ + libwayland-cursor0 \ + libwayland-egl1 \ + libwayland-server0 \ + libxkbcommon0 \ + xdg-utils \ + ca-certificates \ + fonts-liberation \ + libappindicator3-1 \ + libnss3 \ + lsb-base \ + libcurl4 \ + curl && \ + curl -O http://host.docker.internal:8080/microsoft-edge.deb && \ + apt-get -y purge curl && \ + dpkg -i microsoft-edge.deb && \ + ( \ + sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/$PACKAGE || \ + sed -i -e 's@exec -a "$0" "$HERE/msedge"@& --no-sandbox --disable-gpu@' /opt/microsoft/$INSTALL_DIR/microsoft-edge \ + ) && \ + rm microsoft-edge.deb && \ + chown root:root /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \ + chmod 4755 /opt/microsoft/$INSTALL_DIR/msedge-sandbox && \ + microsoft-edge --version && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/firefox/apt/Dockerfile b/static/firefox/apt/Dockerfile new file mode 100644 index 0000000..2b0ecb6 --- /dev/null +++ b/static/firefox/apt/Dockerfile @@ -0,0 +1,20 @@ +FROM browsers/base:7.3.6 + +ARG VERSION +ARG PACKAGE=firefox +ARG PPA + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + ( [ "$PPA" != "" ] && \ + apt-get update && \ + apt-get install -y software-properties-common && \ + apt-get update && \ + add-apt-repository -y $PPA \ + ) || true && \ + apt-get update && \ + apt-get -y --no-install-recommends install iproute2 libavcodec58 $PACKAGE=$VERSION && \ + ( [ "$PACKAGE" != "firefox" ] && ln /usr/bin/$PACKAGE /usr/bin/firefox ) || true && \ + firefox --version && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/firefox/local/Dockerfile b/static/firefox/local/Dockerfile new file mode 100644 index 0000000..99306da --- /dev/null +++ b/static/firefox/local/Dockerfile @@ -0,0 +1,36 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=noop +ARG PACKAGE=firefox +ARG PPA=noop + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + ( \ + ( \ + curl -O http://host.docker.internal:8080/firefox.deb && \ + apt-get update && \ + apt-get -y --no-install-recommends install iproute2 libavcodec58 && \ + apt-get -y install libgtk-3-0 libstartup-notification0 libdbus-glib-1-2 \ + ) || \ + ( \ + curl -O http://host.docker.internal:8080/firefox.deb && \ + dpkg --add-architecture i386 && \ + apt-get update && \ + apt-get -y --no-install-recommends install iproute2 libavcodec58 && \ + apt-get -y install libc6:i386 libncurses5:i386 libstdc++6:i386 libgtk-3-0:i386 libasound2:i386 libdbus-glib-1-2:i386 libxt6:i386 libatomic1:i386 libcairo-gobject2:i386 libstartup-notification0:i386 libx11-xcb1:i386 && \ + mkdir flashplayer && \ + cd flashplayer && \ + curl -o flashplayer.tar.gz https://fpdownload.adobe.com/pub/flashplayer/pdc/32.0.0.387/flash_player_ppapi_linux.i386.tar.gz && \ + tar xvzf flashplayer.tar.gz && \ + cp libpepflashplayer.so /usr/lib/flashplugin-installer/libflashplayer.so && \ + cd .. && \ + rm -Rf flashplayer \ + ) \ + ) && \ + dpkg -i firefox.deb && \ + ( [ "$PACKAGE" != "firefox" ] && ln /usr/bin/$PACKAGE /usr/bin/firefox ) || true && \ + rm firefox.deb && \ + firefox --version && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* && rm -f firefox*.deb diff --git a/static/firefox/selenium/Dockerfile b/static/firefox/selenium/Dockerfile new file mode 100644 index 0000000..65b0c87 --- /dev/null +++ b/static/firefox/selenium/Dockerfile @@ -0,0 +1,16 @@ +ARG VERSION +FROM selenoid/dev_firefox:$VERSION + +RUN \ + apt-get update && \ + apt-get install -y openjdk-8-jre-headless && \ + apt-get clean && \ + rm -Rf /tmp/* + +COPY selenium-server-standalone.jar /usr/share/selenium/ +COPY entrypoint.sh / + +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/firefox/selenium/entrypoint.sh b/static/firefox/selenium/entrypoint.sh new file mode 100755 index 0000000..1898b57 --- /dev/null +++ b/static/firefox/selenium/entrypoint.sh @@ -0,0 +1,53 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$SELENIUM_PID" ]; then + kill -TERM "$SELENIUM_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/java -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar /usr/share/selenium/selenium-server-standalone.jar -port 4444 -browserTimeout 120 & +SELENIUM_PID=$! + +wait diff --git a/static/firefox/selenoid/Dockerfile b/static/firefox/selenoid/Dockerfile new file mode 100644 index 0000000..852e3a9 --- /dev/null +++ b/static/firefox/selenoid/Dockerfile @@ -0,0 +1,12 @@ +ARG VERSION +FROM selenoid/dev_firefox:$VERSION + +COPY geckodriver /usr/bin/ +COPY selenoid /usr/bin/ +COPY --chown=selenium:root browsers.json /home/selenium/ +COPY entrypoint.sh / + +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/firefox/selenoid/browsers.json b/static/firefox/selenoid/browsers.json new file mode 100644 index 0000000..093c008 --- /dev/null +++ b/static/firefox/selenoid/browsers.json @@ -0,0 +1,10 @@ +{ + "firefox": { + "default": "@@VERSION@@", + "versions": { + "@@VERSION@@": { + "image": ["/usr/bin/geckodriver"@@DRIVER_ARGS@@] + } + } + } +} diff --git a/static/firefox/selenoid/entrypoint.sh b/static/firefox/selenoid/entrypoint.sh new file mode 100755 index 0000000..b3d765e --- /dev/null +++ b/static/firefox/selenoid/entrypoint.sh @@ -0,0 +1,94 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +cp /home/selenium/browsers.json /tmp + +VERBOSE=${VERBOSE:-""} +DRIVER_ARGS=${DRIVER_ARGS:-""} +if [ -n "$VERBOSE" ]; then + DRIVER_ARGS="$DRIVER_ARGS, \"--log\", \"debug\"" +fi +sed -i "s|@@DRIVER_ARGS@@|$DRIVER_ARGS|g" /tmp/browsers.json + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$PULSE_PID" ]; then + kill -TERM "$PULSE_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$SELENOID_PID" ]; then + kill -TERM "$SELENOID_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +mkdir -p ~/pulse/.config/pulse +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie +HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1 +HOME=$HOME/pulse pactl load-module module-native-protocol-tcp +PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g') + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/selenoid -conf /tmp/browsers.json -disable-docker -timeout 1h -max-timeout 24h -enable-file-upload -capture-driver-logs & +SELENOID_PID=$! + +if env | grep -q ROOT_CA_; then + while true; do + if certDB=$(ls -d /tmp/rust_mozprofile*/cert9.db 2>/dev/null); then + break + else + sleep 0.1 + fi + done + certdir=$(dirname ${certDB}) + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/cert.pem + certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:${certdir} + if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then + PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'} + openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS} + pk12util -d sql:${certdir} -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS} + rm /tmp/key.p12 + fi + rm /tmp/cert.pem + done +fi + +wait diff --git a/static/opera/Dockerfile b/static/opera/Dockerfile new file mode 100644 index 0000000..4a3df43 --- /dev/null +++ b/static/opera/Dockerfile @@ -0,0 +1,11 @@ +ARG VERSION +FROM selenoid/dev_opera:$VERSION + +COPY operadriver_linux64/operadriver /usr/bin/ +COPY entrypoint.sh / + +RUN chmod +x /usr/bin/operadriver +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/opera/apt/Dockerfile b/static/opera/apt/Dockerfile new file mode 100644 index 0000000..160b48d --- /dev/null +++ b/static/opera/apt/Dockerfile @@ -0,0 +1,16 @@ +FROM browsers/base:7.3.6 + +ARG VERSION +ARG PACKAGE=opera-stable + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + curl -s https://deb.opera.com/archive.key | apt-key add - && \ + echo 'deb https://deb.opera.com/opera-stable/ stable non-free' > /etc/apt/sources.list.d/opera-blink.list && \ + apt-get update && \ + apt-get -y --no-install-recommends install libgtk-3-0 $PACKAGE=$VERSION && \ + ( [ "$PACKAGE" != "opera-stable" ] && ln /usr/bin/$PACKAGE /usr/bin/opera ) || true && \ + opera --version && \ + rm /etc/apt/sources.list.d/$PACKAGE.list && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/opera/entrypoint.sh b/static/opera/entrypoint.sh new file mode 100755 index 0000000..082b067 --- /dev/null +++ b/static/opera/entrypoint.sh @@ -0,0 +1,85 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +VERBOSE=${VERBOSE:-""} +DRIVER_ARGS=${DRIVER_ARGS:-""} +if [ -n "$VERBOSE" ]; then + DRIVER_ARGS="$DRIVER_ARGS --verbose" +fi + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$PULSE_PID" ]; then + kill -TERM "$PULSE_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$DRIVER_PID" ]; then + kill -TERM "$DRIVER_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +if env | grep -q ROOT_CA_; then + mkdir -p $HOME/.pki/nssdb + certutil -N --empty-password -d sql:$HOME/.pki/nssdb + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/cert.pem + certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb + if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then + PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'} + openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS} + pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS} + rm /tmp/key.p12 + fi + rm /tmp/cert.pem + done +fi + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +mkdir -p ~/pulse/.config/pulse +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie +HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1 +HOME=$HOME/pulse pactl load-module module-native-protocol-tcp +PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g') + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/operadriver --port=4444 --whitelisted-ips='' ${DRIVER_ARGS} & +DRIVER_PID=$! + +wait diff --git a/static/opera/local/Dockerfile b/static/opera/local/Dockerfile new file mode 100644 index 0000000..5ba8038 --- /dev/null +++ b/static/opera/local/Dockerfile @@ -0,0 +1,62 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=noop +ARG PACKAGE=opera-stable + +LABEL browser=$PACKAGE:$VERSION + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install gconf-service \ + libasound2 \ + libatk1.0-0 \ + libc6 \ + libcairo2 \ + libcups2 \ + libdbus-1-3 \ + libexpat1 \ + libfontconfig1 \ + libfreetype6 \ + libgcc1 \ + libgconf-2-4 \ + libgdk-pixbuf2.0-0 \ + libglib2.0-0 \ + libgtk2.0-0 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libnotify4 \ + libpango1.0-0 \ + libstdc++6 \ + libx11-6 \ + libx11-xcb1 \ + libxcb1 \ + libxcomposite1 \ + libxcursor1 \ + libxdamage1 \ + libxext6 \ + libxfixes3 \ + libxi6 \ + libxrandr2 \ + libxrender1 \ + libxss1 \ + libxtst6 \ + debconf \ + gnupg \ + libudev1 \ + ca-certificates \ + fonts-liberation \ + libappindicator3-1 \ + libnss3 \ + lsb-base \ + xdg-utils \ + libcurl4 \ + curl && \ + curl -O http://host.docker.internal:8080/opera.deb && \ + apt-get -y purge curl && \ + dpkg -i opera.deb && \ + ( [ "$PACKAGE" != "opera-stable" ] && ln /usr/bin/$PACKAGE /usr/bin/opera ) || true && \ + rm opera.deb && \ + opera --version && \ + rm -Rf /tmp/* && \ + rm -Rf /var/lib/apt/lists/* diff --git a/static/safari/.gitignore b/static/safari/.gitignore new file mode 100644 index 0000000..e1a6ac8 --- /dev/null +++ b/static/safari/.gitignore @@ -0,0 +1 @@ +cmd/prism/prism diff --git a/static/safari/Dockerfile b/static/safari/Dockerfile new file mode 100644 index 0000000..0d6a0a4 --- /dev/null +++ b/static/safari/Dockerfile @@ -0,0 +1,64 @@ +FROM ubuntu:20.04 as build + +ARG WEBKIT_VERSION="610.4.3.1.7" + +RUN \ + apt-get update && \ + apt-get -y install --no-install-recommends ca-certificates subversion && \ + svn checkout https://svn.webkit.org/repository/webkit/tags/Safari-$WEBKIT_VERSION webkit && \ + mkdir -p /opt/webkit && \ + cd webkit && \ + yes | DEBIAN_FRONTEND=noninteractive Tools/gtk/install-dependencies && \ + cmake -DPORT=GTK -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/webkit -DUSE_WPE_RENDERER=OFF -DENABLE_MINIBROWSER=ON -DENABLE_BUBBLEWRAP_SANDBOX=OFF -DENABLE_GAMEPAD=OFF -DENABLE_SPELLCHECK=OFF -DENABLE_WAYLAND_TARGET=OFF -DUSE_OPENJPEG=OFF -DUSE_SOUP2=ON -GNinja && \ + ninja && \ + ninja install && \ + rm -Rf /var/lib/apt/lists/* + +FROM golang:1.17 as go + +COPY cmd/prism /prism + +RUN \ + apt-get update && \ + apt-get install --no-install-recommends -y upx-ucl libx11-dev && \ + cd /prism && \ + GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" && \ + upx /prism/prism && \ + rm -Rf /var/lib/apt/lists/* + +FROM browsers/base:7.3.6 + +COPY --from=build /opt/webkit /opt/webkit +COPY --from=go /prism/prism /usr/bin/ + +ENV LD_LIBRARY_PATH /opt/webkit/lib/:${LD_LIBRARY_PATH} + +RUN \ + apt-get update && \ + apt-get -y install --no-install-recommends \ + libsoup2.4-1 \ + libgtk-3-0 \ + libwebp6 \ + libwebpdemux2 \ + libsecret-1-0 \ + libhyphen0 \ + libwoff1 \ + libharfbuzz-icu0 \ + libgstreamer-gl1.0-0 \ + libopenjp2-7 \ + libnotify4 \ + libxslt1.1 \ + libegl1 && \ + ldconfig && \ + apt-get clean && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* && \ + chmod 777 /etc/ssl/certs && \ + mkdir /tmp/ca-certificates && \ + chmod 777 /tmp/ca-certificates + +COPY entrypoint.sh / + +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/safari/cmd/prism/go.mod b/static/safari/cmd/prism/go.mod new file mode 100644 index 0000000..5c8c774 --- /dev/null +++ b/static/safari/cmd/prism/go.mod @@ -0,0 +1,3 @@ +module github.com/aerokube/webkit-images/prism + +go 1.17 diff --git a/static/safari/cmd/prism/main.go b/static/safari/cmd/prism/main.go new file mode 100644 index 0000000..2bafe41 --- /dev/null +++ b/static/safari/cmd/prism/main.go @@ -0,0 +1,150 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/http/httputil" + "net/url" + "os" + "os/signal" + "path" + "syscall" + "time" +) + +var ( + listen = ":4444" + target = "http://localhost:5555" + waitTimeout = 30 * time.Second + gracePeriod = 30 * time.Second + browserName = "safari" + browserVersion = "15.0" +) + +func wait(ctx context.Context, target string) (*url.URL, error) { + for { + r, err := http.NewRequest(http.MethodHead, target, http.NoBody) + if err != nil { + return nil, fmt.Errorf("new %s request to %s: %v", http.MethodHead, target, err) + } + resp, err := http.DefaultClient.Do(r.WithContext(ctx)) + if resp != nil { + resp.Body.Close() + } + if err != nil { + if err, ok := err.(*url.Error); ok { + switch err.Err { + case context.Canceled, context.DeadlineExceeded: + return nil, err + default: + <-time.After(100 * time.Millisecond) + continue + } + } + } + return r.URL, nil + } +} + +func main() { + ctx, cancel := context.WithCancel(context.Background()) + e := make(chan error) + go func() { + stop := make(chan os.Signal) + signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) + select { + case err := <-e: + log.Fatalf("server: %v", err) + case <-stop: + cancel() + } + }() + waitCtx, waitCancel := context.WithTimeout(ctx, waitTimeout) + defer waitCancel() + u, err := wait(waitCtx, target) + if err != nil { + log.Fatal(fmt.Errorf("wait target: %v", err)) + } + server := &http.Server{ + Addr: listen, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var value map[string]interface{} + err := json.NewDecoder(r.Body).Decode(&value) + if err != nil && err != io.EOF { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err == nil { + if _, ok := value["desiredCapabilities"]; ok { + delete(value, "desiredCapabilities") + } + if o, ok := value["capabilities"]; ok { + if w3cCapabilities, ok := o.(map[string]interface{}); ok { + for _, match := range []string{"alwaysMatch", "firstMatch"} { + delete(w3cCapabilities, match) + } + } + } + body, err := json.Marshal(value) + if err != nil { + log.Printf("[ERROR] marshalling capabilities: %v", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + r.Body = ioutil.NopCloser(bytes.NewReader(body)) + r.ContentLength = int64(len(body)) + } + (&httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.URL.Scheme, r.URL.Host, r.URL.Path = u.Scheme, u.Host, path.Join(u.Path, r.URL.Path) + }, + ModifyResponse: func(resp *http.Response) error { + if resp.StatusCode != http.StatusOK { + return nil + } + var values map[string]interface{} + defer resp.Body.Close() + err := json.NewDecoder(resp.Body).Decode(&values) + if err != nil { + return fmt.Errorf("decode json response: %v", err) + } + if o, ok := values["value"]; ok { + if value, ok := o.(map[string]interface{}); ok { + if o, ok := value["capabilities"]; ok { + if capabilities, ok := o.(map[string]interface{}); ok { + capabilities["browserName"] = browserName + capabilities["browserVersion"] = browserVersion + delete(capabilities, "platformName") + } + } + } + } + buf, err := json.Marshal(&values) + if err != nil { + return fmt.Errorf("encode json response: %v", err) + } + resp.Header.Del("Server") + resp.Header.Del("Content-Length") + resp.ContentLength = int64(len(buf)) + resp.Body = ioutil.NopCloser(bytes.NewReader(buf)) + return nil + }, + }).ServeHTTP(w, r) + }), + } + go func() { + e <- server.ListenAndServe() + }() + <-ctx.Done() + shCtx, shCancel := context.WithTimeout(context.Background(), gracePeriod) + defer shCancel() + if err := server.Shutdown(shCtx); err != nil { + log.Fatalf("graceful shutdown: %v]", err) + } +} diff --git a/static/safari/entrypoint.sh b/static/safari/entrypoint.sh new file mode 100755 index 0000000..b4707ba --- /dev/null +++ b/static/safari/entrypoint.sh @@ -0,0 +1,74 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +QUIET=${QUIET:-""} +DRIVER_ARGS="" +if [ -z "$QUIET" ]; then + DRIVER_ARGS="--verbose" +fi + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$DRIVER_PID" ]; then + kill -TERM "$DRIVER_PID" + fi + if [ -n "$PRISM_PID" ]; then + kill -TERM "$PRISM_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi +} + +trap clean SIGINT SIGTERM + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +if env | grep -q ROOT_CA_; then + mkdir -p /tmp/ca-certificates + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/ca-certificates/${certname}.crt + done + update-ca-certificates --localcertsdir /tmp/ca-certificates +fi + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" >/dev/null 2>&1 & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /opt/webkit/bin/WebKitWebDriver --port=5555 --host=0.0.0.0 ${DRIVER_ARGS} & +DRIVER_PID=$! + +/usr/bin/prism & +PRISM_PID=$! + +wait diff --git a/static/yandex/Dockerfile b/static/yandex/Dockerfile new file mode 100644 index 0000000..11ddc6e --- /dev/null +++ b/static/yandex/Dockerfile @@ -0,0 +1,11 @@ +ARG VERSION +FROM selenoid/dev_yandex:$VERSION + +COPY yandexdriver /usr/bin/ +COPY entrypoint.sh / + +RUN chmod +x /usr/bin/yandexdriver +USER selenium + +EXPOSE 4444 +ENTRYPOINT ["/entrypoint.sh"] diff --git a/static/yandex/apt/Dockerfile b/static/yandex/apt/Dockerfile new file mode 100644 index 0000000..a99858f --- /dev/null +++ b/static/yandex/apt/Dockerfile @@ -0,0 +1,14 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=19.4.2.698-1 + +LABEL browser=yandex-browser-beta:$VERSION + +RUN \ + curl -s https://repo.yandex.ru/yandex-browser/YANDEX-BROWSER-KEY.GPG | apt-key add - && \ + echo 'deb [arch=amd64] https://repo.yandex.ru/yandex-browser/deb beta main' > /etc/apt/sources.list.d/yandex-browser.list && \ + apt-get update && \ + apt-get -y --no-install-recommends install yandex-browser-beta=$VERSION && \ + yandex-browser-beta --version && \ + rm /etc/apt/sources.list.d/yandex-browser.list && \ + rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* diff --git a/static/yandex/entrypoint.sh b/static/yandex/entrypoint.sh new file mode 100755 index 0000000..9eda7d3 --- /dev/null +++ b/static/yandex/entrypoint.sh @@ -0,0 +1,85 @@ +#!/bin/bash +SCREEN_RESOLUTION=${SCREEN_RESOLUTION:-"1920x1080x24"} +DISPLAY_NUM=99 +export DISPLAY=":$DISPLAY_NUM" + +VERBOSE=${VERBOSE:-""} +DRIVER_ARGS=${DRIVER_ARGS:-""} +if [ -n "$VERBOSE" ]; then + DRIVER_ARGS="$DRIVER_ARGS --verbose" +fi + +clean() { + if [ -n "$FILESERVER_PID" ]; then + kill -TERM "$FILESERVER_PID" + fi + if [ -n "$XSELD_PID" ]; then + kill -TERM "$XSELD_PID" + fi + if [ -n "$XVFB_PID" ]; then + kill -TERM "$XVFB_PID" + fi + if [ -n "$DRIVER_PID" ]; then + kill -TERM "$DRIVER_PID" + fi + if [ -n "$X11VNC_PID" ]; then + kill -TERM "$X11VNC_PID" + fi + if [ -n "$PULSE_PID" ]; then + kill -TERM "$PULSE_PID" + fi +} + +trap clean SIGINT SIGTERM + +if env | grep -q ROOT_CA_; then + mkdir -p $HOME/.pki/nssdb + certutil -N --empty-password -d sql:$HOME/.pki/nssdb + for e in $(env | grep ROOT_CA_ | sed -e 's/=.*$//'); do + certname=$(echo -n $e | sed -e 's/ROOT_CA_//') + echo ${!e} | base64 -d >/tmp/cert.pem + certutil -A -n ${certname} -t "TC,C,T" -i /tmp/cert.pem -d sql:$HOME/.pki/nssdb + if cat tmp/cert.pem | grep -q "PRIVATE KEY"; then + PRIVATE_KEY_PASS=${PRIVATE_KEY_PASS:-\'\'} + openssl pkcs12 -export -in /tmp/cert.pem -clcerts -nodes -out /tmp/key.p12 -passout pass:${PRIVATE_KEY_PASS} -passin pass:${PRIVATE_KEY_PASS} + pk12util -d sql:$HOME/.pki/nssdb -i /tmp/key.p12 -W ${PRIVATE_KEY_PASS} + rm /tmp/key.p12 + fi + rm /tmp/cert.pem + done +fi + +/usr/bin/fileserver & +FILESERVER_PID=$! + +DISPLAY="$DISPLAY" /usr/bin/xseld & +XSELD_PID=$! + +mkdir -p ~/pulse/.config/pulse +echo -n 'gIvST5iz2S0J1+JlXC1lD3HWvg61vDTV1xbmiGxZnjB6E3psXsjWUVQS4SRrch6rygQgtpw7qmghDFTaekt8qWiCjGvB0LNzQbvhfs1SFYDMakmIXuoqYoWFqTJ+GOXYByxpgCMylMKwpOoANEDePUCj36nwGaJNTNSjL8WBv+Bf3rJXqWnJ/43a0hUhmBBt28Dhiz6Yqowa83Y4iDRNJbxih6rB1vRNDKqRr/J9XJV+dOlM0dI+K6Vf5Ag+2LGZ3rc5sPVqgHgKK0mcNcsn+yCmO+XLQHD1K+QgL8RITs7nNeF1ikYPVgEYnc0CGzHTMvFR7JLgwL2gTXulCdwPbg=='| base64 -d>~/pulse/.config/pulse/cookie +HOME=$HOME/pulse pulseaudio --start --exit-idle-time=-1 +HOME=$HOME/pulse pactl load-module module-native-protocol-tcp +PULSE_PID=$(ps --no-headers -C pulseaudio -o pid | sed -r 's/( )+//g') + +/usr/bin/xvfb-run -l -n "$DISPLAY_NUM" -s "-ac -screen 0 $SCREEN_RESOLUTION -noreset -listen tcp" /usr/bin/fluxbox -display "$DISPLAY" -log /dev/null 2>/dev/null & +XVFB_PID=$! + +retcode=1 +until [ $retcode -eq 0 ]; do + DISPLAY="$DISPLAY" wmctrl -m >/dev/null 2>&1 + retcode=$? + if [ $retcode -ne 0 ]; then + echo Waiting X server... + sleep 0.1 + fi +done + +if [ "$ENABLE_VNC" == "true" ]; then + x11vnc -display "$DISPLAY" -passwd selenoid -shared -forever -loop500 -rfbport 5900 -rfbportv6 5900 -logfile /dev/null & + X11VNC_PID=$! +fi + +DISPLAY="$DISPLAY" /usr/bin/yandexdriver --port=4444 --allowed-ips='' --allowed-origins='*' ${DRIVER_ARGS} & +DRIVER_PID=$! + +wait diff --git a/static/yandex/local/Dockerfile b/static/yandex/local/Dockerfile new file mode 100644 index 0000000..bf09eae --- /dev/null +++ b/static/yandex/local/Dockerfile @@ -0,0 +1,60 @@ +FROM browsers/base:7.3.6 + +ARG VERSION=noop + +LABEL browser=yandex-browser-beta:$VERSION + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install gconf-service \ + libasound2 \ + libatk1.0-0 \ + libc6 \ + libcairo2 \ + libcups2 \ + libdbus-1-3 \ + libexpat1 \ + libfontconfig1 \ + libfreetype6 \ + libgcc1 \ + libgconf-2-4 \ + libgdk-pixbuf2.0-0 \ + libglib2.0-0 \ + libgtk2.0-0 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libnotify4 \ + libpango1.0-0 \ + libstdc++6 \ + libx11-6 \ + libx11-xcb1 \ + libxcb1 \ + libxcomposite1 \ + libxcursor1 \ + libxdamage1 \ + libxext6 \ + libxfixes3 \ + libxi6 \ + libxrandr2 \ + libxrender1 \ + libxss1 \ + libxtst6 \ + debconf \ + gnupg \ + libudev1 \ + ca-certificates \ + fonts-liberation \ + libappindicator3-1 \ + libnss3 \ + lsb-base \ + xdg-utils \ + libcurl4 \ + curl && \ + curl -O http://apt-repo:8080/yandex-browser.deb && \ + apt-get -y purge curl && \ + dpkg -i yandex-browser.deb && \ + rm yandex-browser.deb && \ + yandex-browser-beta --version && \ + rm -Rf /tmp/* && \ + rm -Rf /var/lib/apt/lists/*