From 235cfb4f14f3adbf378827d5fa070c416ad15288 Mon Sep 17 00:00:00 2001 From: Sami Kankaristo Date: Wed, 5 Jun 2024 21:53:37 +0300 Subject: [PATCH] WIP CI workflows and Fastlane Issue: SIMPLYE-381 --- .../check-build-number.yml | 0 .../non-drm-build.yml | 0 .../release-on-merge.yml | 0 .../release.yml | 0 .../unit-testing.yml | 0 .../upload-on-merge.yml | 0 .../upload.yml | 0 .github/workflows/README.md | 88 + .github/workflows/ios-main.yml | 81 + .github/workflows/ios-pr.yml | 78 + .github/workflows/ios-release.yml | 84 + .gitignore | 18 +- Cartfile => Cartfile.example | 0 ...file.resolved => Cartfile.resolved.example | 0 Gemfile.lock | 18 +- Palace.xcodeproj/project.pbxproj | 2785 +++++++++++++- .../xcshareddata/xcschemes/Ekirjasto.xcscheme | 12 +- .../xcschemes/Palace-noDRM.xcscheme | 2 +- .../xcshareddata/xcschemes/Palace.xcscheme | 2 +- Palace/Accounts/Library/AccountsManager.swift | 15 +- Palace/AppInfrastructure/TPPAppDelegate.swift | 2 +- .../TPPConfiguration+Ekirjasto.swift | 17 +- Palace/Book/Models/TPPBookCoverRegistry.swift | 2 +- Palace/Book/Models/TPPBookRegistry.swift | 4 +- Palace/Book/UI/TPPBookButtonsView.h | 24 +- Palace/Book/UI/TPPBookButtonsView.m | 1 + .../Catalog/TPPCatalogNavigationController.m | 2 +- .../Catalog/TPPCatalogSearchViewController.m | 1 + ....json => Ekirjasto_Catalog_Feed_beta.json} | 0 ...d.json => Ekirjasto_Catalog_Feed_dev.json} | 0 ...son => Ekirjasto_Catalog_Feed_ellibs.json} | 0 ...=> Ekirjasto_Catalog_Feed_production.json} | 0 ..._Feed.json => TestLogin_Catalog_Feed.json} | 0 .../prod_Ekirjasto_Catalog_Feed.json | 59 - .../PDF/Model/TPPEncryptedPDFDataProvider.m | 2 + .../Transifex/TransifexManager.swift | 5 +- .../Localization/Transifex/txstrings.json | 3258 ++++++++++++++++- ...plist.example => GoogleService-Info.plist} | 18 +- .../xcshareddata/swiftpm/Package.resolved | 104 - RDServices.xcodeproj/project.pbxproj | 558 ++- README-Palace.md | 76 + README.md | 121 +- RELEASING-Palace.md | 81 + RELEASING.md | 131 +- fastlane/.gitignore | 5 + fastlane/Appfile | 1 - fastlane/Fastfile | 143 +- fastlane/Matchfile | 2 +- fastlane/README.md | 28 +- ios-audiobooktoolkit | 2 +- metadata/en-US/changelog.txt | 2 + metadata/fi-FI/changelog.txt | 2 + metadata/sv-SE/changelog.txt | 2 + .../adobe-rmsdk-build.sh | 0 .../archive-and-upload-adhoc.sh | 0 {scripts => palace-scripts}/bootstrap-drm.sh | 0 .../build-3rd-party-dependencies.sh | 45 + .../build-carthage-R2-integration.sh | 0 palace-scripts/build-carthage.sh | 51 + .../build-openssl-curl.sh | 0 {scripts => palace-scripts}/build_curl.sh | 0 {scripts => palace-scripts}/build_openssl.sh | 0 .../create-release-notes.sh | 0 .../decode-install-secrets.sh | 0 .../firebase-upload-symbols.sh | 0 .../firebase-upload.sh | 0 palace-scripts/firebase/run | 76 + palace-scripts/firebase/upload-symbols | Bin 0 -> 285440 bytes .../install-profile.sh | 0 .../ios-binaries-check.sh | 0 .../ios-binaries-upload.sh | 0 .../ios-check-version.sh | 0 {scripts => palace-scripts}/release-notes.sh | 0 {scripts => palace-scripts}/setup-repo-drm.sh | 0 .../setup-repo-nodrm.sh | 0 .../testflight-upload.sh | 0 .../update-certificates.sh | 0 {scripts => palace-scripts}/xcode-archive.sh | 0 .../xcode-build-nodrm.sh | 0 .../xcode-export-adhoc.sh | 0 .../xcode-export-appstore.sh | 0 {scripts => palace-scripts}/xcode-settings.sh | 0 {scripts => palace-scripts}/xcode-test.sh | 0 scripts/bootstrap.sh | 105 + scripts/build-3rd-party-dependencies.sh | 79 +- scripts/build-carthage.sh | 98 +- scripts/build.sh | 92 + scripts/clean.sh | 68 + scripts/fastlane.sh | 30 + scripts/release-checks.sh | 167 + scripts/reveal-secrets.sh | 128 + scripts/run-tests.sh | 59 + scripts/setup-repo-nodrm-github.sh | 46 - scripts/show-ci-info.sh | 27 + scripts/transifex.sh | 201 + scripts/version.sh | 266 ++ 96 files changed, 8778 insertions(+), 596 deletions(-) rename .github/{workflows => palace-workflows}/check-build-number.yml (100%) rename .github/{workflows => palace-workflows}/non-drm-build.yml (100%) rename .github/{workflows => palace-workflows}/release-on-merge.yml (100%) rename .github/{workflows => palace-workflows}/release.yml (100%) rename .github/{workflows => palace-workflows}/unit-testing.yml (100%) rename .github/{workflows => palace-workflows}/upload-on-merge.yml (100%) rename .github/{workflows => palace-workflows}/upload.yml (100%) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/ios-main.yml create mode 100644 .github/workflows/ios-pr.yml create mode 100644 .github/workflows/ios-release.yml rename Cartfile => Cartfile.example (100%) rename Cartfile.resolved => Cartfile.resolved.example (100%) rename Palace/EkirjastoConfig/{beta_Ekirjasto_Catalog_Feed.json => Ekirjasto_Catalog_Feed_beta.json} (100%) rename Palace/EkirjastoConfig/{Test_Catalog_Feed.json => Ekirjasto_Catalog_Feed_dev.json} (100%) rename Palace/EkirjastoConfig/{ellibs_Ekirjasto_Catalog_Feed.json => Ekirjasto_Catalog_Feed_ellibs.json} (100%) rename Palace/EkirjastoConfig/{Ekirjasto_Catalog_Feed.json => Ekirjasto_Catalog_Feed_production.json} (100%) rename Palace/EkirjastoConfig/{dev_Ekirjasto_Catalog_Feed.json => TestLogin_Catalog_Feed.json} (100%) delete mode 100644 Palace/EkirjastoConfig/prod_Ekirjasto_Catalog_Feed.json rename PalaceConfig/{GoogleService-Info.plist.example => GoogleService-Info.plist} (59%) delete mode 100644 PalaceR2.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 README-Palace.md create mode 100644 RELEASING-Palace.md create mode 100644 fastlane/.gitignore create mode 100644 metadata/en-US/changelog.txt create mode 100644 metadata/fi-FI/changelog.txt create mode 100644 metadata/sv-SE/changelog.txt rename {scripts => palace-scripts}/adobe-rmsdk-build.sh (100%) rename {scripts => palace-scripts}/archive-and-upload-adhoc.sh (100%) rename {scripts => palace-scripts}/bootstrap-drm.sh (100%) create mode 100755 palace-scripts/build-3rd-party-dependencies.sh rename {scripts => palace-scripts}/build-carthage-R2-integration.sh (100%) create mode 100755 palace-scripts/build-carthage.sh rename {scripts => palace-scripts}/build-openssl-curl.sh (100%) rename {scripts => palace-scripts}/build_curl.sh (100%) rename {scripts => palace-scripts}/build_openssl.sh (100%) rename {scripts => palace-scripts}/create-release-notes.sh (100%) rename {scripts => palace-scripts}/decode-install-secrets.sh (100%) rename {scripts => palace-scripts}/firebase-upload-symbols.sh (100%) rename {scripts => palace-scripts}/firebase-upload.sh (100%) create mode 100755 palace-scripts/firebase/run create mode 100755 palace-scripts/firebase/upload-symbols rename {scripts => palace-scripts}/install-profile.sh (100%) rename {scripts => palace-scripts}/ios-binaries-check.sh (100%) rename {scripts => palace-scripts}/ios-binaries-upload.sh (100%) rename {scripts => palace-scripts}/ios-check-version.sh (100%) rename {scripts => palace-scripts}/release-notes.sh (100%) rename {scripts => palace-scripts}/setup-repo-drm.sh (100%) rename {scripts => palace-scripts}/setup-repo-nodrm.sh (100%) rename {scripts => palace-scripts}/testflight-upload.sh (100%) rename {scripts => palace-scripts}/update-certificates.sh (100%) rename {scripts => palace-scripts}/xcode-archive.sh (100%) rename {scripts => palace-scripts}/xcode-build-nodrm.sh (100%) rename {scripts => palace-scripts}/xcode-export-adhoc.sh (100%) rename {scripts => palace-scripts}/xcode-export-appstore.sh (100%) rename {scripts => palace-scripts}/xcode-settings.sh (100%) rename {scripts => palace-scripts}/xcode-test.sh (100%) create mode 100755 scripts/bootstrap.sh create mode 100755 scripts/build.sh create mode 100755 scripts/clean.sh create mode 100755 scripts/fastlane.sh create mode 100755 scripts/release-checks.sh create mode 100755 scripts/reveal-secrets.sh create mode 100755 scripts/run-tests.sh delete mode 100755 scripts/setup-repo-nodrm-github.sh create mode 100755 scripts/show-ci-info.sh create mode 100755 scripts/transifex.sh create mode 100755 scripts/version.sh diff --git a/.github/workflows/check-build-number.yml b/.github/palace-workflows/check-build-number.yml similarity index 100% rename from .github/workflows/check-build-number.yml rename to .github/palace-workflows/check-build-number.yml diff --git a/.github/workflows/non-drm-build.yml b/.github/palace-workflows/non-drm-build.yml similarity index 100% rename from .github/workflows/non-drm-build.yml rename to .github/palace-workflows/non-drm-build.yml diff --git a/.github/workflows/release-on-merge.yml b/.github/palace-workflows/release-on-merge.yml similarity index 100% rename from .github/workflows/release-on-merge.yml rename to .github/palace-workflows/release-on-merge.yml diff --git a/.github/workflows/release.yml b/.github/palace-workflows/release.yml similarity index 100% rename from .github/workflows/release.yml rename to .github/palace-workflows/release.yml diff --git a/.github/workflows/unit-testing.yml b/.github/palace-workflows/unit-testing.yml similarity index 100% rename from .github/workflows/unit-testing.yml rename to .github/palace-workflows/unit-testing.yml diff --git a/.github/workflows/upload-on-merge.yml b/.github/palace-workflows/upload-on-merge.yml similarity index 100% rename from .github/workflows/upload-on-merge.yml rename to .github/palace-workflows/upload-on-merge.yml diff --git a/.github/workflows/upload.yml b/.github/palace-workflows/upload.yml similarity index 100% rename from .github/workflows/upload.yml rename to .github/palace-workflows/upload.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 000000000..53eec2429 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,88 @@ +# GitHub Actions workflows + +This directory contains E-kirjasto iOS CI workflows. + + +## Secrets + +Secrets are stored in GitHub Actions and are available to the workflows as +environment variables. +The secrets are stored in the respective repository, +so secrets for the Android CI workflows are stored in ekirjasto-android-core, +while secrets for the iOS CI workflows are stored in ekirjasto-ios-core, etc. + +GitHub Actions doesn't directly support storing files, so files are stored as +base64 encoded strings and decoded back into files (by `scripts/reveal-secrets.sh`). + +[ekirjasto-ci-helper](https://github.com/NatLibFi/ekirjasto-ci-helper) is used +to manage the secrets. +It cannot read the secrets, but it can be used to set or delete secrets. +It requires a GitHub personal access token with rights to the repository. + + +### iOS secrets + +The secrets in use for the iOS CI workflows are: + +| Secret name | Environment variable | Format | Description | +|-----------------------------------------|----------------------------------------------------------|--------|--------------------------------------------------| +| FASTLANE_APP_STORE_CONNECT_API_KEY_JSON | EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64 | base64 | App Store Connect API key JSON (base64 encoded) | +| LIBLCP_DEPENDECY_SECRET | EKIRJASTO_LIBLCP_DEPENDENCY_SECRET | text | The secret part of the liblcp dependency path | +| MATCH_PASSWORD | MATCH_PASSWORD | text | Password for Fastlane match (ekirjasto-ios-keys) | +| SSH_PRIVATE_KEY | N/A | text | SSH private key (E-kirjasto CI machine account) | +| TRANSIFEX_SECRET | EKIRJASTO_IOS_TRANSIFEX_SECRET | text | The iOS Transifex secret | +| TRANSIFEX_TOKEN | EKIRJASTO_IOS_TRANSIFEX_TOKEN | text | The iOS Transifex token | + + +### Log masking secrets + +In addition to the above secrets, there are some additional values where the +name starts with `MASK_`. These secrets are not used at all in the build, and +their purpose just to mask the values from GitHub Actions logs (there are other +ways to achieve log masking, but this is the easiest method). + +For example, the liblcp dependency path in `Cartfile` is a secret and should be +masked in logs, but the entire file is stored as one secret, so the individual +dependecy path would not be automatically masked without the `MASK_*` secrets. + + +## iOS CI workflows + +### ios-pr.yml + +This workflow is run for every commit pushed to a PR. + +This workflow builds a debug build with the production configuration, +and release builds for the dev, beta, and productions configurations, +and runs tests. + + +### ios-main.yml + +This workflow is run for every commit pushed to the main branch. +Direct commits to main are disabled, so essentially this is run for merged PRs. + +This workflow does the same builds and runs the same tests as the PR workflow, +but in addition to those, the dev, beta and production release builds are uploaded to Testflight. +Before the uploads, some minimal release checks are run, +so that uploads wouldn't fail because of things like a version suffix. + + +### ios-release.yml + +This workflow is run for commits on release/* branches (e.g. release/1.2.3). + +This workflow is mostly the same as the main CI workflow, +meaning that all builds and tests are run, +and the same uploads are made, but some additional release checks are made. + +Before the uploads some additional checks are run: +- there must not be any suffix in the version name (also checked in the main workflow) + - while Xcode allows using a suffix for iOS apps, App Store Connect will not allow using any suffix +- the version number must be increased from the one currently in main +- all Transifex strings must be committed into the repository + - i.e. `scripts/transifex.sh` must not find new strings to download + +The main purpose of this workflow is to automate releasing a new version, +but not everything is automated (by design). See [RELEASING.md](/RELEASING.md) +for what to do after upload and more info about E-kirjasto's releasing process. diff --git a/.github/workflows/ios-main.yml b/.github/workflows/ios-main.yml new file mode 100644 index 000000000..834351ae1 --- /dev/null +++ b/.github/workflows/ios-main.yml @@ -0,0 +1,81 @@ +name: ios-main + +# +# This workflow is run on all commits pushed to main (i.e. merged PRs). +# + +on: + push: + branches: [ main ] + +env: + COMMIT_SHA: ${{ github.sha }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + TARGET_BRANCH_NAME: ${{ github.base_ref || github.ref_name }} + # Join all secrets, so that they're "used", and will be masked in logs + MASKED_SECRETS: ${{ join(secrets, '\n') }} + +jobs: + build: + runs-on: macOS-13 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout submodules + run: git submodule update --init --recursive + - name: Show build info + env: + TEST_SECRET: ${{ secrets.MASK_TEST }} + run: scripts/show-ci-info.sh + + - name: SSH setup (for cloning ekirjasto-ios-keys through Fastlane match) + uses: MrSquaare/ssh-setup-action@v3.1.0 + with: + private-key-name: ekirjasto-ci-ed25519 + private-key: ${{ secrets.SSH_PRIVATE_KEY }} + host: github.com + - name: Force Xcode 15 + run: sudo xcode-select -switch /Applications/Xcode_15.0.1.app + + - name: Bootstrap (and reveal secrets) + env: + EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64: ${{ secrets.FASTLANE_APP_STORE_CONNECT_API_KEY_JSON }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + EKIRJASTO_LIBLCP_DEPENDENCY_SECRET: ${{ secrets.LIBLCP_DEPENDENCY_SECRET }} + # Carthage gets rate limited in GitHub Actions if unauthenticated + # (they're all public repositories, so auth isn't otherwise necessary) + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: scripts/bootstrap.sh --overwrite-secrets + + - name: App version and build number consistency check + run: scripts/version.sh --check + + - name: Upload and download Transifex localizations + env: + EKIRJASTO_IOS_TRANSIFEX_SECRET: ${{ secrets.TRANSIFEX_SECRET }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + run: scripts/transifex.sh --append-tags=main + + - name: Build debug build + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh debug + + - name: Run tests + if: ${{ !cancelled() }} + run: scripts/run-tests.sh + + - name: Run minimal release checks + run: scripts/release-checks.sh --minimal + - name: Build release build and upload to Testflight (config=production) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:production + - name: Build release build and upload to Testflight (config=beta) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:beta + - name: Build release build and upload to Testflight (config=dev) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:dev diff --git a/.github/workflows/ios-pr.yml b/.github/workflows/ios-pr.yml new file mode 100644 index 000000000..c0a6976ca --- /dev/null +++ b/.github/workflows/ios-pr.yml @@ -0,0 +1,78 @@ +name: ios-pr + +# +# This workflow is run on all PRs (before they're merged). +# + +on: + pull_request: + branches: [ main ] + +env: + COMMIT_SHA: ${{ github.sha }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + TARGET_BRANCH_NAME: ${{ github.base_ref || github.ref_name }} + # Join all secrets, so that they're "used", and will be masked in logs + MASKED_SECRETS: ${{ join(secrets, '\n') }} + +jobs: + build: + runs-on: macOS-13 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout submodules + run: git submodule update --init --recursive + - name: Show build info + env: + TEST_SECRET: ${{ secrets.MASK_TEST }} + run: scripts/show-ci-info.sh + + - name: SSH setup (for cloning ekirjasto-ios-keys through Fastlane match) + uses: MrSquaare/ssh-setup-action@v3.1.0 + with: + private-key-name: ekirjasto-ci-ed25519 + private-key: ${{ secrets.SSH_PRIVATE_KEY }} + host: github.com + - name: Force Xcode 15 + run: sudo xcode-select -switch /Applications/Xcode_15.0.1.app + + - name: Bootstrap (and reveal secrets) + env: + EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64: ${{ secrets.FASTLANE_APP_STORE_CONNECT_API_KEY_JSON }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + EKIRJASTO_LIBLCP_DEPENDENCY_SECRET: ${{ secrets.LIBLCP_DEPENDENCY_SECRET }} + # Carthage gets rate-limited in GitHub Actions if unauthenticated + # (they're all public repositories, so auth isn't otherwise necessary) + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: scripts/bootstrap.sh --overwrite-secrets + + - name: App version and build number consistency check + run: scripts/version.sh --check + + - name: Build debug build + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh debug + - name: Build release build + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release + + # TODO:SAMI: Remove these steps from the PR workflow, only here for testing + - name: Build release build and upload to Testflight (config=production) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:production + - name: Build release build and upload to Testflight (config=beta) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:beta + - name: Build release build and upload to Testflight (config=dev) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:dev + + - name: Run tests + if: ${{ !cancelled() }} + run: scripts/run-tests.sh diff --git a/.github/workflows/ios-release.yml b/.github/workflows/ios-release.yml new file mode 100644 index 000000000..e53c9110a --- /dev/null +++ b/.github/workflows/ios-release.yml @@ -0,0 +1,84 @@ +name: ios-main + +# +# This workflow is run for all commits in release/* branches. +# + +on: + push: + branches: [ main ] + +env: + COMMIT_SHA: ${{ github.sha }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + TARGET_BRANCH_NAME: ${{ github.base_ref || github.ref_name }} + # Join all secrets, so that they're "used", and will be masked in logs + MASKED_SECRETS: ${{ join(secrets, '\n') }} + +jobs: + build: + runs-on: macOS-13 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout submodules + run: git submodule update --init --recursive + - name: Show build info + env: + TEST_SECRET: ${{ secrets.MASK_TEST }} + run: scripts/show-ci-info.sh + + - name: SSH setup (for cloning ekirjasto-ios-keys through Fastlane match) + uses: MrSquaare/ssh-setup-action@v3.1.0 + with: + private-key-name: ekirjasto-ci-ed25519 + private-key: ${{ secrets.SSH_PRIVATE_KEY }} + host: github.com + - name: Force Xcode 15 + run: sudo xcode-select -switch /Applications/Xcode_15.0.1.app + + - name: Bootstrap (and reveal secrets) + env: + EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64: ${{ secrets.FASTLANE_APP_STORE_CONNECT_API_KEY_JSON }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + EKIRJASTO_LIBLCP_DEPENDENCY_SECRET: ${{ secrets.LIBLCP_DEPENDENCY_SECRET }} + # Carthage gets rate limited in GitHub Actions if unauthenticated + # (they're all public repositories, so auth isn't otherwise necessary) + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: scripts/bootstrap.sh --overwrite-secrets + + - name: App version and build number consistency check + run: scripts/version.sh --check + + - name: Upload and download Transifex localizations + env: + EKIRJASTO_IOS_TRANSIFEX_SECRET: ${{ secrets.TRANSIFEX_SECRET }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + run: scripts/transifex.sh --append-tags=release + + - name: Build debug build + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh debug + + - name: Run tests + if: ${{ !cancelled() }} + run: scripts/run-tests.sh + + - name: Run release checks + env: + EKIRJASTO_IOS_TRANSIFEX_SECRET: ${{ secrets.TRANSIFEX_SECRET }} + EKIRJASTO_IOS_TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }} + run: scripts/release-checks.sh + - name: Build release build and upload to Testflight (config=production) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:production + - name: Build release build and upload to Testflight (config=beta) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:beta + - name: Build release build and upload to Testflight (config=dev) + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: scripts/build.sh release_upload config:dev diff --git a/.gitignore b/.gitignore index da4e8bdee..a11e393eb 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,24 @@ adobe-rmsdk **/ReaderClientCert.sig **/APIKeys.swift Carthage* -**/GoogleService-Info.plist +#**/GoogleService-Info.plist **/TPPSecrets.swift fastlane/report.xml fastlane/*_output Palace.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved + +# Ignore temporary files +temp/ + +# Ignore Cartfile and Carfile.resolved (the bootstrap script copies them into +# place, and they can contain a liblcp secret, so they shouldn't be committed) +Cartfile +Cartfile.resolved + +# Ignore build files +*.dSYM.zip +*.ipa + +# Ignore txios-cli (Transifex CLI tool), it's auto-downloaded and built +txios-cli + diff --git a/Cartfile b/Cartfile.example similarity index 100% rename from Cartfile rename to Cartfile.example diff --git a/Cartfile.resolved b/Cartfile.resolved.example similarity index 100% rename from Cartfile.resolved rename to Cartfile.resolved.example diff --git a/Gemfile.lock b/Gemfile.lock index 878f4944e..db9390f8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,17 +10,17 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.933.0) - aws-sdk-core (3.196.1) + aws-partitions (1.942.0) + aws-sdk-core (3.197.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.82.0) - aws-sdk-core (~> 3, >= 3.193.0) + aws-sdk-kms (1.83.0) + aws-sdk-core (~> 3, >= 3.197.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.151.0) - aws-sdk-core (~> 3, >= 3.194.0) + aws-sdk-s3 (1.152.1) + aws-sdk-core (~> 3, >= 3.197.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.8) aws-sigv4 (1.8.0) @@ -147,7 +147,7 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) @@ -171,8 +171,8 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.8) - strscan (>= 3.0.9) + rexml (3.2.9) + strscan rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) diff --git a/Palace.xcodeproj/project.pbxproj b/Palace.xcodeproj/project.pbxproj index 73158a7aa..3b3a4e1c8 100644 --- a/Palace.xcodeproj/project.pbxproj +++ b/Palace.xcodeproj/project.pbxproj @@ -223,6 +223,9 @@ 21F4BF3B26BC62D4000CF592 /* AdobeCertificate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F4BF3926BC62D4000CF592 /* AdobeCertificate.swift */; }; 21F7D3CB275A9D3C0080B44B /* String+HTMLEntities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F7D3CA275A9D3C0080B44B /* String+HTMLEntities.swift */; }; 21F7D3CC275A9D3C0080B44B /* String+HTMLEntities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F7D3CA275A9D3C0080B44B /* String+HTMLEntities.swift */; }; + 260CAD4E2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_ellibs.json in Resources */ = {isa = PBXBuildFile; fileRef = 260CAD4B2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_ellibs.json */; }; + 260CAD4F2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_beta.json in Resources */ = {isa = PBXBuildFile; fileRef = 260CAD4C2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_beta.json */; }; + 260CAD502C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_dev.json in Resources */ = {isa = PBXBuildFile; fileRef = 260CAD4D2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_dev.json */; }; 2D2B47841D08F8E2007F7764 /* UpdateCheckUpToDate.json in Resources */ = {isa = PBXBuildFile; fileRef = 2D2B47691D08F264007F7764 /* UpdateCheckUpToDate.json */; }; 2D2B478E1D08FDF5007F7764 /* UpdateCheckNeedsUpdate.json in Resources */ = {isa = PBXBuildFile; fileRef = 2D2B478A1D08FC78007F7764 /* UpdateCheckNeedsUpdate.json */; }; 2D2B478F1D08FDF5007F7764 /* UpdateCheckUnknown.json in Resources */ = {isa = PBXBuildFile; fileRef = 2D2B47891D08FC78007F7764 /* UpdateCheckUnknown.json */; }; @@ -241,7 +244,7 @@ 2DEF10BA201ECCEA0082843A /* TPPMyBooksSimplifiedBearerToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DEF10B9201ECCEA0082843A /* TPPMyBooksSimplifiedBearerToken.m */; }; 2DF321831DC3B83500E1858F /* TPPAnnotations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF321821DC3B83500E1858F /* TPPAnnotations.swift */; }; 2DFAC8ED1CD8DDD1003D9EC0 /* TPPOPDSCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFAC8EC1CD8DDD1003D9EC0 /* TPPOPDSCategory.m */; }; - 309262C42BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed.json */; }; + 309262C42BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed_production.json in Resources */ = {isa = PBXBuildFile; fileRef = 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed_production.json */; }; 331262DD2A287F53006BA87D /* LibraryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A2299E240F3BEA006B9EAD /* LibraryService.swift */; }; 331262DE2A287F53006BA87D /* TPPR2Owner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A2299A240F3B9B006B9EAD /* TPPR2Owner.swift */; }; 331262DF2A287F53006BA87D /* TPPLibraryDescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0826CD2E24AA2801000F4030 /* TPPLibraryDescriptionCell.swift */; }; @@ -614,7 +617,6 @@ 33266EFB2A4037B6003BC347 /* Asap-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 33266EFA2A4037B6003BC347 /* Asap-Regular.ttf */; }; 33266F012A40456D003BC347 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33266F002A40456D003BC347 /* Images.xcassets */; }; 33266F032A40459E003BC347 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33266F022A40459E003BC347 /* Colors.xcassets */; }; - 33266F042A40476B003BC347 /* Ekirjasto-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 335223852A28BC2500CD514D /* Ekirjasto-Info.plist */; }; 33305E7B2AC5A428005DC75F /* TPPBookCellDelegate+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5024A8C2A0E8761006BF653 /* TPPBookCellDelegate+Extensions.swift */; }; 33372CF72AC548EA0001BE2F /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 33372CF62AC548EA0001BE2F /* FirebaseAnalytics */; }; 33372CF92AC548FB0001BE2F /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 33372CF82AC548FB0001BE2F /* FirebaseCrashlytics */; }; @@ -685,9 +687,9 @@ 36A527E12BDBC4F9009101F5 /* TestLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36A527E02BDBC4F9009101F5 /* TestLoginViewController.swift */; }; 36A527E22BDBC4F9009101F5 /* TestLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36A527E02BDBC4F9009101F5 /* TestLoginViewController.swift */; }; 36A527E32BDBC4F9009101F5 /* TestLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36A527E02BDBC4F9009101F5 /* TestLoginViewController.swift */; }; - 36A527E92BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* Test_Catalog_Feed.json */; }; - 36A527EA2BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* Test_Catalog_Feed.json */; }; - 36A527EB2BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* Test_Catalog_Feed.json */; }; + 36A527E92BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* TestLogin_Catalog_Feed.json */; }; + 36A527EA2BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* TestLogin_Catalog_Feed.json */; }; + 36A527EB2BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */ = {isa = PBXBuildFile; fileRef = 36A527E82BDBD399009101F5 /* TestLogin_Catalog_Feed.json */; }; 36BBC78E2B920EB300E8E426 /* EkirjastoUserLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363C62092B14EEA300858AA5 /* EkirjastoUserLoginView.swift */; }; 36BBC78F2B920EB300E8E426 /* EkirjastoArrowDownButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3379F81E2A5D418400E9945F /* EkirjastoArrowDownButton.swift */; }; 36BBC7902B920EB300E8E426 /* EkirjastoFacetFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3379F8102A5D3C4B00E9945F /* EkirjastoFacetFilterView.swift */; }; @@ -1712,6 +1714,9 @@ 21F4BF3926BC62D4000CF592 /* AdobeCertificate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdobeCertificate.swift; sourceTree = ""; }; 21F634E426D828CF00C8BE87 /* ReadiumLCP.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ReadiumLCP.xcframework; path = Carthage/Build/ReadiumLCP.xcframework; sourceTree = ""; }; 21F7D3CA275A9D3C0080B44B /* String+HTMLEntities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HTMLEntities.swift"; sourceTree = ""; }; + 260CAD4B2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_ellibs.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Ekirjasto_Catalog_Feed_ellibs.json; sourceTree = ""; }; + 260CAD4C2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_beta.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Ekirjasto_Catalog_Feed_beta.json; sourceTree = ""; }; + 260CAD4D2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_dev.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Ekirjasto_Catalog_Feed_dev.json; sourceTree = ""; }; 2D2B47621D08F1ED007F7764 /* PalaceTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PalaceTests-Bridging-Header.h"; sourceTree = ""; }; 2D2B47691D08F264007F7764 /* UpdateCheckUpToDate.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = UpdateCheckUpToDate.json; sourceTree = ""; }; 2D2B47721D08F807007F7764 /* PalaceTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PalaceTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1741,7 +1746,7 @@ 2DF321821DC3B83500E1858F /* TPPAnnotations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TPPAnnotations.swift; sourceTree = ""; }; 2DFAC8EB1CD8DDD1003D9EC0 /* TPPOPDSCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPOPDSCategory.h; sourceTree = ""; }; 2DFAC8EC1CD8DDD1003D9EC0 /* TPPOPDSCategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPOPDSCategory.m; sourceTree = ""; }; - 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Ekirjasto_Catalog_Feed.json; sourceTree = ""; }; + 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed_production.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Ekirjasto_Catalog_Feed_production.json; sourceTree = ""; }; 3312646E2A287F53006BA87D /* Ekirjasto.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ekirjasto.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33266EF82A4036DC003BC347 /* UIFont+Ekirjasto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Ekirjasto.swift"; sourceTree = ""; }; 33266EFA2A4037B6003BC347 /* Asap-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Asap-Regular.ttf"; sourceTree = ""; }; @@ -1766,7 +1771,7 @@ 36A07DBB2BB5B49C00583E0B /* PasskeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasskeyView.swift; sourceTree = ""; }; 36A527DC2BDBC0EA009101F5 /* TestLoginUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestLoginUI.swift; sourceTree = ""; }; 36A527E02BDBC4F9009101F5 /* TestLoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestLoginViewController.swift; sourceTree = ""; }; - 36A527E82BDBD399009101F5 /* Test_Catalog_Feed.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Test_Catalog_Feed.json; sourceTree = ""; }; + 36A527E82BDBD399009101F5 /* TestLogin_Catalog_Feed.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = TestLogin_Catalog_Feed.json; sourceTree = ""; }; 52545184217A76FF00BBC1B4 /* TPPUserNotifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TPPUserNotifications.swift; sourceTree = ""; }; 52592BB721220A1100587288 /* TPPLocalization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPPLocalization.m; sourceTree = ""; }; 52592BBB21220A4F00587288 /* TPPLocalization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TPPLocalization.h; sourceTree = ""; }; @@ -2469,9 +2474,12 @@ 33266EFF2A404545003BC347 /* EkirjastoConfig */ = { isa = PBXGroup; children = ( - 36A527E82BDBD399009101F5 /* Test_Catalog_Feed.json */, + 36A527E82BDBD399009101F5 /* TestLogin_Catalog_Feed.json */, 3360FBA52A41B2DA00AC1905 /* Ekirjasto_Launch_Screen.storyboard */, - 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed.json */, + 309262C32BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed_production.json */, + 260CAD4C2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_beta.json */, + 260CAD4D2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_dev.json */, + 260CAD4B2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_ellibs.json */, 335223852A28BC2500CD514D /* Ekirjasto-Info.plist */, 33266F002A40456D003BC347 /* Images.xcassets */, 33266F022A40459E003BC347 /* Colors.xcassets */, @@ -3944,7 +3952,7 @@ attributes = { CLASSPREFIX = TPP; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 1420; + LastUpgradeCheck = 1540; ORGANIZATIONNAME = "The Palace Project"; TargetAttributes = { 2D2B47711D08F807007F7764 = { @@ -4015,10 +4023,10 @@ ); projectRoot = ""; targets = ( + 331262D32A287F53006BA87D /* Ekirjasto */, A823D80C192BABA400B55DE2 /* Palace */, 73EB0A6325821DF4006BC997 /* Palace-noDRM */, 2D2B47711D08F807007F7764 /* PalaceTests */, - 331262D32A287F53006BA87D /* Ekirjasto */, ); }; /* End PBXProject section */ @@ -4150,9 +4158,10 @@ 3312644E2A287F53006BA87D /* Localizable.stringsdict in Resources */, 3312644F2A287F53006BA87D /* software-licenses.html in Resources */, 33266F012A40456D003BC347 /* Images.xcassets in Resources */, - 36A527EB2BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */, + 36A527EB2BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */, 331264512A287F53006BA87D /* Accounts.json in Resources */, - 33266F042A40476B003BC347 /* Ekirjasto-Info.plist in Resources */, + 260CAD4E2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_ellibs.json in Resources */, + 260CAD4F2C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_beta.json in Resources */, 331264522A287F53006BA87D /* InfoPlist.strings in Resources */, 331264532A287F53006BA87D /* OpenSans-Bold.ttf in Resources */, 331264542A287F53006BA87D /* reader.html in Resources */, @@ -4163,12 +4172,13 @@ 3372514A2A9F4ED30072DA02 /* Asap-Bold.ttf in Resources */, 3312645A2A287F53006BA87D /* OpenSans-SemiBold.ttf in Resources */, 3312645B2A287F53006BA87D /* OpenDyslexic3-Bold.ttf in Resources */, + 260CAD502C1A0F7200BD54C6 /* Ekirjasto_Catalog_Feed_dev.json in Resources */, 3312645C2A287F53006BA87D /* readium-shared-js_all.js.map in Resources */, 3312645E2A287F53006BA87D /* TPPReaderPositions.storyboard in Resources */, 3312645F2A287F53006BA87D /* host_app_feedback.js in Resources */, 33372CFC2AC54B8A0001BE2F /* GoogleService-Info.plist in Resources */, 33266EFB2A4037B6003BC347 /* Asap-Regular.ttf in Resources */, - 309262C42BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed.json in Resources */, + 309262C42BFD57EB003CCA2F /* Ekirjasto_Catalog_Feed_production.json in Resources */, 331264612A287F53006BA87D /* txstrings.json in Resources */, 331264622A287F53006BA87D /* readium-shared-js_all.js.bundles.js in Resources */, 331264632A287F53006BA87D /* OpenDyslexic3-Regular.ttf in Resources */, @@ -4205,7 +4215,7 @@ 73EB0B6B25821DF4006BC997 /* readium-shared-js_all.js.bundles.js in Resources */, 73EB0B6C25821DF4006BC997 /* OpenDyslexic3-Regular.ttf in Resources */, 73EB0B6D25821DF4006BC997 /* GoogleService-Info.plist in Resources */, - 36A527EA2BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */, + 36A527EA2BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4239,7 +4249,7 @@ 5A6929241B95C8B400FB4C10 /* readium-shared-js_all.js.bundles.js in Resources */, 84B7A3481B84E8FE00584FB2 /* OpenDyslexic3-Regular.ttf in Resources */, 738EF2D02405E38800F388FB /* GoogleService-Info.plist in Resources */, - 36A527E92BDBD399009101F5 /* Test_Catalog_Feed.json in Resources */, + 36A527E92BDBD399009101F5 /* TestLogin_Catalog_Feed.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4289,6 +4299,7 @@ }; 331264652A287F53006BA87D /* Copy Frameworks (Carthage) */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -4307,6 +4318,7 @@ }; 331264662A287F53006BA87D /* Crashlytics */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 8; files = ( ); @@ -4328,6 +4340,7 @@ }; 33FCF7E32AC457D6008E3B72 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 12; files = ( ); @@ -5584,149 +5597,209 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 2D2B477A1D08F808007F7764 /* Debug */ = { + 260CAD232C1A0C7400BD54C6 /* Debug-ellibs */ = { isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_CXX_LIBRARY = "libc++"; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Manual; - DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = 88CBA74T8K; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-ellibs"; + }; + 260CAD242C1A0C7400BD54C6 /* Debug-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)", "$(PROJECT_DIR)/Carthage/Build", ); - GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", + "EKIRJASTO=1", "SIMPLYE=1", "LCP=1", + "CONF_ELLIBS=1", ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SDKROOT)/usr/include/libxml2\"", - "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", - "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", - "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", - "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", - "\"$(SRCROOT)/adept-ios\"", - "\"$(SRCROOT)/adobe-content-filter/public\"", - "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", - "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", - ); - INFOPLIST_FILE = PalaceTests/Info.plist; + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; - PRODUCT_NAME = PalaceTests; + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG EKIRJASTO SIMPLYE LCP CONF_ELLIBS"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = ( "-Wall", "-Wextra", - "-Weverything", - "-Wno-objc-missing-property-synthesis", - "-Wno-c11-extensions", "-Wno-documentation", "-Wno-c++98-compat-pedantic", "-Wno-c++98-compat", - "-Wno-gnu-statement-expression", - "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", ); + WRAPPER_EXTENSION = app; }; - name = Debug; + name = "Debug-ellibs"; }; - 2D2B477B1D08F808007F7764 /* Release */ = { + 260CAD252C1A0C7400BD54C6 /* Debug-ellibs */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_UNREACHABLE_CODE = YES; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 88CBA74T8K; - ENABLE_STRICT_OBJC_MSGSEND = YES; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)", "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", ); - GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "SIMPLYE=1", + "DEBUG=1", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SDKROOT)/usr/include/libxml2\"", - "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", - "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", - "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", - "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", - "\"$(SRCROOT)/adept-ios\"", - "\"$(SRCROOT)/adobe-content-filter/public\"", - "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", - "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", - ); - INFOPLIST_FILE = PalaceTests/Info.plist; + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; - PRODUCT_NAME = PalaceTests; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "Ad Hoc"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = ( "-Wall", "-Wextra", - "-Weverything", - "-Wno-objc-missing-property-synthesis", - "-Wno-c11-extensions", "-Wno-documentation", "-Wno-c++98-compat-pedantic", "-Wno-c++98-compat", - "-Wno-gnu-statement-expression", - "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", ); + WRAPPER_EXTENSION = app; }; - name = Release; + name = "Debug-ellibs"; }; - 3312646C2A287F53006BA87D /* Debug */ = { + 260CAD262C1A0C7400BD54C6 /* Debug-ellibs */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; - CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 161; - DEVELOPMENT_TEAM = QA5XMCRV5M; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -5739,23 +5812,21 @@ "SIMPLYE=1", "DEBUG=1", "$(inherited)", - "LCP=1", ); - INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.30; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PRODUCT_MODULE_NAME = Palace; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "2e185b6c-271e-4b02-a05e-860b8c3831f6"; PROVISIONING_PROFILE_SPECIFIER = ""; RUN_CLANG_STATIC_ANALYZER = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE LCP"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE"; SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; @@ -5772,32 +5843,2448 @@ ); WRAPPER_EXTENSION = app; }; - name = Debug; + name = "Debug-ellibs"; }; - 3312646D2A287F53006BA87D /* Release */ = { + 260CAD272C1A0C7400BD54C6 /* Debug-ellibs */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; - CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 161; - DEVELOPMENT_TEAM = QA5XMCRV5M; - ENABLE_BITCODE = NO; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)", "$(PROJECT_DIR)/Carthage/Build", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", "SIMPLYE=1", - "DEBUG=0", + "LCP=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Debug-ellibs"; + }; + 260CAD282C1A0C8500BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-dev"; + }; + 260CAD292C1A0C8500BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_DEV=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG EKIRJASTO SIMPLYE LCP CONF_DEV"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-dev"; + }; + 260CAD2A2C1A0C8500BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=1", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "Ad Hoc"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-dev"; + }; + 260CAD2B2C1A0C8500BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "2e185b6c-271e-4b02-a05e-860b8c3831f6"; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-dev"; + }; + 260CAD2C2C1A0C8500BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "LCP=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Debug-dev"; + }; + 260CAD2D2C1A0C9000BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-beta"; + }; + 260CAD2E2C1A0C9000BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_BETA=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG EKIRJASTO SIMPLYE LCP CONF_BETA"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-beta"; + }; + 260CAD2F2C1A0C9000BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=1", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "Ad Hoc"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-beta"; + }; + 260CAD302C1A0C9000BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "2e185b6c-271e-4b02-a05e-860b8c3831f6"; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-beta"; + }; + 260CAD312C1A0C9000BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "LCP=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Debug-beta"; + }; + 260CAD322C1A0C9800BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-production"; + }; + 260CAD332C1A0C9800BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_PRODUCTION=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG EKIRJASTO SIMPLYE LCP CONF_PRODUCTION"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-production"; + }; + 260CAD342C1A0C9800BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=1", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "Ad Hoc"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-production"; + }; + 260CAD352C1A0C9800BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "2e185b6c-271e-4b02-a05e-860b8c3831f6"; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SIMPLYE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Debug-production"; + }; + 260CAD362C1A0C9800BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "LCP=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Debug-production"; + }; + 260CAD372C1A0CB600BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + DEFINES_MODULE = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=0"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = "Release-ellibs"; + }; + 260CAD382C1A0CB600BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_ELLIBS=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "EKIRJASTO SIMPLYE LCP CONF_ELLIBS"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-ellibs"; + }; + 260CAD392C1A0CB600BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=0", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-ellibs"; + }; + 260CAD3A2C1A0CB600BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=0", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "b3d9154d-70e1-48d6-a0c5-869431277a5c"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SIMPLYE; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-ellibs"; + }; + 260CAD3B2C1A0CB600BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Release-ellibs"; + }; + 260CAD3C2C1A0CD100BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + DEFINES_MODULE = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=0"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = "Release-dev"; + }; + 260CAD3D2C1A0CD100BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_DEV=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "EKIRJASTO SIMPLYE LCP CONF_DEV"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-dev"; + }; + 260CAD3E2C1A0CD100BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=0", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-dev"; + }; + 260CAD3F2C1A0CD100BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=0", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "b3d9154d-70e1-48d6-a0c5-869431277a5c"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SIMPLYE; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-dev"; + }; + 260CAD402C1A0CD100BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Release-dev"; + }; + 260CAD412C1A0CD800BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + DEFINES_MODULE = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=0"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = "Release-beta"; + }; + 260CAD422C1A0CD800BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_BETA=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "EKIRJASTO SIMPLYE LCP CONF_BETA"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-beta"; + }; + 260CAD432C1A0CD800BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=0", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-beta"; + }; + 260CAD442C1A0CD800BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=0", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "b3d9154d-70e1-48d6-a0c5-869431277a5c"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SIMPLYE; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-beta"; + }; + 260CAD452C1A0CD800BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Release-beta"; + }; + 260CAD462C1A0CDF00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CAE35BBA1B86289500BF9BC5 /* Palace.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_GCD_PERFORMANCE = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + DEFINES_MODULE = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=0"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-ld_classic", + ); + PRODUCT_NAME = Palace; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = "Release-production"; + }; + 260CAD472C1A0CDF00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + "CONF_PRODUCTION=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "EKIRJASTO SIMPLYE LCP CONF_PRODUCTION"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-production"; + }; + 260CAD482C1A0CDF00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "DEBUG=0", + "FEATURE_DRM_CONNECTOR=1", + "FEATURE_CRASH_REPORTING=1", + "LCP=1", + "FEATURE_OVERDRIVE=1", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SIMPLYE FEATURE_DRM_CONNECTOR FEATURE_CRASH_REPORTING LCP FEATURE_OVERDRIVE"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-production"; + }; + 260CAD492C1A0CDF00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = 88CBA74T8K; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SIMPLYE=1", + "DEBUG=0", + "$(inherited)", + ); + INFOPLIST_FILE = "PalaceConfig/Palace-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "Palace-noDRM"; + PROVISIONING_PROFILE = "b3d9154d-70e1-48d6-a0c5-869431277a5c"; + PROVISIONING_PROFILE_SPECIFIER = "App Store"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SIMPLYE; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = "Release-production"; + }; + 260CAD4A2C1A0CDF00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = "Release-production"; + }; + 2D2B477A1D08F808007F7764 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + "LCP=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = Debug; + }; + 2D2B477B1D08F808007F7764 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 88CBA74T8K; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SIMPLYE=1", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/include/libxml2\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/RDServices\"", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"", + "\"$(SRCROOT)/ios-tenprintcover/TenPrintCover\"", + "\"$(SRCROOT)/ios-audiobook-overdrive/OverdriveProcessor\"", + "\"$(SRCROOT)/adept-ios\"", + "\"$(SRCROOT)/adobe-content-filter/public\"", + "\"$(SRCROOT)/adobe-rmsdk/dp/public\"", + "\"$(SRCROOT)/adobe-rmsdk/xml/uft/public\"", + ); + INFOPLIST_FILE = PalaceTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjastoTests"; + PRODUCT_NAME = PalaceTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PalaceTests/PalaceTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.2; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Ekirjasto.app/Ekirjasto"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Weverything", + "-Wno-objc-missing-property-synthesis", + "-Wno-c11-extensions", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-gnu-statement-expression", + "-Wno-gnu-zero-variadic-macro-arguments", + ); + }; + name = Release; + }; + 3312646C2A287F53006BA87D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", + "LCP=1", + ); + INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "E-kirjasto"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.books"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.33; + PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; + PRODUCT_MODULE_NAME = Palace; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; + RUN_CLANG_STATIC_ANALYZER = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG EKIRJASTO SIMPLYE LCP"; + SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-documentation", + "-Wno-c++98-compat-pedantic", + "-Wno-c++98-compat", + "-Wno-c11-extensions", + "-Wno-objc-missing-property-synthesis", + ); + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 3312646D2A287F53006BA87D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 10000; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = QA5XMCRV5M; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Carthage/Build", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Palace/AppInfrastructure/Palace-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "EKIRJASTO=1", + "SIMPLYE=1", "LCP=1", ); INFOPLIST_FILE = "Palace/EkirjastoConfig/Ekirjasto-Info.plist"; @@ -5808,13 +8295,14 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.30; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PRODUCT_MODULE_NAME = Palace; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc fi.kansalliskirjasto.e-kirjasto"; RUN_CLANG_STATIC_ANALYZER = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SIMPLYE LCP"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "EKIRJASTO SIMPLYE LCP"; SWIFT_OBJC_BRIDGING_HEADER = "Palace/AppInfrastructure/Palace-Bridging-Header.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; @@ -5842,7 +8330,7 @@ CODE_SIGN_ENTITLEMENTS = Palace/PalaceDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 10000; DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -5863,7 +8351,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.35; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PRODUCT_MODULE_NAME = Palace; PRODUCT_NAME = "Palace-noDRM"; @@ -5899,7 +8387,7 @@ CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 10000; DEVELOPMENT_TEAM = 88CBA74T8K; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -5921,7 +8409,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.35; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PRODUCT_MODULE_NAME = Palace; PRODUCT_NAME = "Palace-noDRM"; @@ -6002,7 +8490,7 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-ld64", + "-ld_classic", ); PRODUCT_NAME = Palace; SDKROOT = iphoneos; @@ -6049,6 +8537,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=0"; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -6059,7 +8548,7 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-ld64", + "-ld_classic", ); PRODUCT_NAME = Palace; SDKROOT = iphoneos; @@ -6083,7 +8572,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 10000; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -6110,7 +8599,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.35; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PROVISIONING_PROFILE_SPECIFIER = "Ad Hoc"; RUN_CLANG_STATIC_ANALYZER = YES; @@ -6143,7 +8632,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 10000; DEVELOPMENT_TEAM = 88CBA74T8K; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -6170,7 +8659,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.35; + MARKETING_VERSION = 1.0.33; PRODUCT_BUNDLE_IDENTIFIER = "fi.kansalliskirjasto.e-kirjasto"; PROVISIONING_PROFILE_SPECIFIER = "App Store"; RUN_CLANG_STATIC_ANALYZER = YES; @@ -6199,7 +8688,15 @@ isa = XCConfigurationList; buildConfigurations = ( 2D2B477A1D08F808007F7764 /* Debug */, + 260CAD272C1A0C7400BD54C6 /* Debug-ellibs */, + 260CAD2C2C1A0C8500BD54C6 /* Debug-dev */, + 260CAD312C1A0C9000BD54C6 /* Debug-beta */, + 260CAD362C1A0C9800BD54C6 /* Debug-production */, 2D2B477B1D08F808007F7764 /* Release */, + 260CAD3B2C1A0CB600BD54C6 /* Release-ellibs */, + 260CAD402C1A0CD100BD54C6 /* Release-dev */, + 260CAD452C1A0CD800BD54C6 /* Release-beta */, + 260CAD4A2C1A0CDF00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -6208,7 +8705,15 @@ isa = XCConfigurationList; buildConfigurations = ( 3312646C2A287F53006BA87D /* Debug */, + 260CAD242C1A0C7400BD54C6 /* Debug-ellibs */, + 260CAD292C1A0C8500BD54C6 /* Debug-dev */, + 260CAD2E2C1A0C9000BD54C6 /* Debug-beta */, + 260CAD332C1A0C9800BD54C6 /* Debug-production */, 3312646D2A287F53006BA87D /* Release */, + 260CAD382C1A0CB600BD54C6 /* Release-ellibs */, + 260CAD3D2C1A0CD100BD54C6 /* Release-dev */, + 260CAD422C1A0CD800BD54C6 /* Release-beta */, + 260CAD472C1A0CDF00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -6217,7 +8722,15 @@ isa = XCConfigurationList; buildConfigurations = ( 73EB0B7325821DF4006BC997 /* Debug */, + 260CAD262C1A0C7400BD54C6 /* Debug-ellibs */, + 260CAD2B2C1A0C8500BD54C6 /* Debug-dev */, + 260CAD302C1A0C9000BD54C6 /* Debug-beta */, + 260CAD352C1A0C9800BD54C6 /* Debug-production */, 73EB0B7425821DF4006BC997 /* Release */, + 260CAD3A2C1A0CB600BD54C6 /* Release-ellibs */, + 260CAD3F2C1A0CD100BD54C6 /* Release-dev */, + 260CAD442C1A0CD800BD54C6 /* Release-beta */, + 260CAD492C1A0CDF00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -6226,7 +8739,15 @@ isa = XCConfigurationList; buildConfigurations = ( A823D837192BABA400B55DE2 /* Debug */, + 260CAD232C1A0C7400BD54C6 /* Debug-ellibs */, + 260CAD282C1A0C8500BD54C6 /* Debug-dev */, + 260CAD2D2C1A0C9000BD54C6 /* Debug-beta */, + 260CAD322C1A0C9800BD54C6 /* Debug-production */, A823D838192BABA400B55DE2 /* Release */, + 260CAD372C1A0CB600BD54C6 /* Release-ellibs */, + 260CAD3C2C1A0CD100BD54C6 /* Release-dev */, + 260CAD412C1A0CD800BD54C6 /* Release-beta */, + 260CAD462C1A0CDF00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -6235,7 +8756,15 @@ isa = XCConfigurationList; buildConfigurations = ( A823D83A192BABA400B55DE2 /* Debug */, + 260CAD252C1A0C7400BD54C6 /* Debug-ellibs */, + 260CAD2A2C1A0C8500BD54C6 /* Debug-dev */, + 260CAD2F2C1A0C9000BD54C6 /* Debug-beta */, + 260CAD342C1A0C9800BD54C6 /* Debug-production */, A823D83B192BABA400B55DE2 /* Release */, + 260CAD392C1A0CB600BD54C6 /* Release-ellibs */, + 260CAD3E2C1A0CD100BD54C6 /* Release-dev */, + 260CAD432C1A0CD800BD54C6 /* Release-beta */, + 260CAD482C1A0CDF00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Palace.xcodeproj/xcshareddata/xcschemes/Ekirjasto.xcscheme b/Palace.xcodeproj/xcshareddata/xcschemes/Ekirjasto.xcscheme index 4cbadca1b..702707446 100644 --- a/Palace.xcodeproj/xcshareddata/xcschemes/Ekirjasto.xcscheme +++ b/Palace.xcodeproj/xcshareddata/xcschemes/Ekirjasto.xcscheme @@ -1,6 +1,6 @@ @@ -56,7 +56,7 @@ + buildConfiguration = "Debug-dev"> diff --git a/Palace.xcodeproj/xcshareddata/xcschemes/Palace-noDRM.xcscheme b/Palace.xcodeproj/xcshareddata/xcschemes/Palace-noDRM.xcscheme index 8e452ff04..9e23b9fdd 100644 --- a/Palace.xcodeproj/xcshareddata/xcschemes/Palace-noDRM.xcscheme +++ b/Palace.xcodeproj/xcshareddata/xcschemes/Palace-noDRM.xcscheme @@ -1,6 +1,6 @@ ())?) { Log.debug(#file, "Entering loadCatalog... useTestEnv \(TPPConfiguration.useTestEnv)") - let targetUrl = TPPConfiguration.customUrl() ?? (TPPSettings.shared.useBetaLibraries ? TPPConfiguration.betaUrl : (TPPConfiguration.useTestEnv ? TPPConfiguration.testUrl : TPPConfiguration.prodUrl)) + let targetUrl = TPPConfiguration.customUrl() ?? (TPPConfiguration.useTestEnv ? TPPConfiguration.testUrl : TPPConfiguration.prodUrl) let hash = targetUrl.absoluteString.md5().base64EncodedStringUrlSafe() .trimmingCharacters(in: ["="]) @@ -382,12 +387,12 @@ let currentAccountIdentifierKey = "TPPCurrentAccountIdentifier" func updateAccountSet(completion: ((Bool) -> ())?) { performLocked { - self.accountSet = TPPConfiguration.customUrlHash() ?? (TPPSettings.shared.useBetaLibraries ? TPPConfiguration.betaUrlHash : TPPConfiguration.useTestEnv ? TPPConfiguration.testUrlHash : TPPConfiguration.prodUrlHash) + self.accountSet = TPPConfiguration.customUrlHash() ?? (TPPConfiguration.useTestEnv ? TPPConfiguration.testUrlHash : TPPConfiguration.prodUrlHash) } if self.accounts().isEmpty || TPPConfiguration.customUrlHash() != nil { loadCatalogs(completion: completion) - } + } } func clearCache() { diff --git a/Palace/AppInfrastructure/TPPAppDelegate.swift b/Palace/AppInfrastructure/TPPAppDelegate.swift index a32ac5221..a3c60aef7 100644 --- a/Palace/AppInfrastructure/TPPAppDelegate.swift +++ b/Palace/AppInfrastructure/TPPAppDelegate.swift @@ -21,7 +21,7 @@ class TPPAppDelegate: UIResponder, UIApplicationDelegate { // MARK: - Application Lifecycle func applicationDidFinishLaunching(_ application: UIApplication) { - //FirebaseApp.configure() + FirebaseApp.configure() TPPErrorLogger.configureCrashAnalytics() // Perform data migrations as early as possible before anything has a chance to access them diff --git a/Palace/AppInfrastructure/TPPConfiguration+Ekirjasto.swift b/Palace/AppInfrastructure/TPPConfiguration+Ekirjasto.swift index 440c619d8..881d9c40f 100644 --- a/Palace/AppInfrastructure/TPPConfiguration+Ekirjasto.swift +++ b/Palace/AppInfrastructure/TPPConfiguration+Ekirjasto.swift @@ -12,16 +12,25 @@ extension TPPConfiguration { static let registryHashKey = "registryHashKey" - static let betaUrl = URL(string: "https://registry.palaceproject.io/libraries/qa")! + //static let betaUrl = URL(string: "https://registry.palaceproject.io/libraries/qa")! //static let prodUrl = URL(string: "https://registry.palaceproject.io/libraries")! + #if CONF_ELLIBS + private static let feedFileUrlBase = "Ekirjasto_Catalog_Feed_ellibs" + #elseif CONF_DEV + private static let feedFileUrlBase = "Ekirjasto_Catalog_Feed_dev" + #elseif CONF_BETA + private static let feedFileUrlBase = "Ekirjasto_Catalog_Feed_beta" + #else + private static let feedFileUrlBase = "Ekirjasto_Catalog_Feed_production" + #endif private static let feedFileUrl = URL(fileURLWithPath: - Bundle.main.path(forResource: "Ekirjasto_Catalog_Feed", + Bundle.main.path(forResource: feedFileUrlBase, ofType: "json")!) private static let testFeedFileUrl = URL(fileURLWithPath: - Bundle.main.path(forResource: "Test_Catalog_Feed", + Bundle.main.path(forResource: "TestLogin_Catalog_Feed", ofType: "json")!) private static let feedFileUrlHash = feedFileUrl.absoluteString.md5().base64EncodedStringUrlSafe().trimmingCharacters(in: ["="]) @@ -30,7 +39,7 @@ extension TPPConfiguration { static var testUrl = testFeedFileUrl - static let betaUrlHash = betaUrl.absoluteString.md5().base64EncodedStringUrlSafe().trimmingCharacters(in: ["="]) + //static let betaUrlHash = betaUrl.absoluteString.md5().base64EncodedStringUrlSafe().trimmingCharacters(in: ["="]) //static let prodUrlHash = prodUrl.absoluteString.md5().base64EncodedStringUrlSafe().trimmingCharacters(in: ["="]) static let prodUrlHash = feedFileUrlHash diff --git a/Palace/Book/Models/TPPBookCoverRegistry.swift b/Palace/Book/Models/TPPBookCoverRegistry.swift index 810690c82..0f9275477 100644 --- a/Palace/Book/Models/TPPBookCoverRegistry.swift +++ b/Palace/Book/Models/TPPBookCoverRegistry.swift @@ -72,7 +72,7 @@ class TPPBookCoverRegistry { var _books : [TPPBook] = [] - for var b in books { + for b in books { if !_books.contains(where: { book in book.identifier == b.identifier }) { diff --git a/Palace/Book/Models/TPPBookRegistry.swift b/Palace/Book/Models/TPPBookRegistry.swift index 2ad096dd1..25a90a289 100644 --- a/Palace/Book/Models/TPPBookRegistry.swift +++ b/Palace/Book/Models/TPPBookRegistry.swift @@ -234,14 +234,14 @@ class TPPBookRegistry: NSObject, TPPBookRegistrySyncing { } state = .syncing syncUrl = loansUrl - print("book registry syncUrl 1: \(syncUrl)") + print("book registry syncUrl 1: \(syncUrl as URL?)") TPPOPDSFeed.withURL(loansUrl, shouldResetCache: true) { feed, errorDocument in print("book registry withURL!") DispatchQueue.main.async { defer { self.state = .loaded self.syncUrl = nil - print("book registry syncUrl 2: \(self.syncUrl)") + print("book registry syncUrl 2: \(self.syncUrl as URL?)") } if self.syncUrl != loansUrl { return diff --git a/Palace/Book/UI/TPPBookButtonsView.h b/Palace/Book/UI/TPPBookButtonsView.h index a6848a72c..37b12a5b8 100644 --- a/Palace/Book/UI/TPPBookButtonsView.h +++ b/Palace/Book/UI/TPPBookButtonsView.h @@ -6,23 +6,23 @@ @protocol TPPBookButtonsDelegate -- (void)didSelectReturnForBook:(TPPBook *)book completion:(void (^ _Nullable)(void))completion; -- (void)didSelectDownloadForBook:(TPPBook *)book; -- (void)didSelectReadForBook:(TPPBook *)book; -- (void)didSelectPlaySample:(TPPBook *)book; +- (void)didSelectReturnForBook:(TPPBook *_Null_unspecified)book completion:(void (^ _Nullable)(void))completion; +- (void)didSelectDownloadForBook:(TPPBook *_Null_unspecified)book; +- (void)didSelectReadForBook:(TPPBook *_Null_unspecified)book; +- (void)didSelectPlaySample:(TPPBook *_Null_unspecified)book; @end @protocol TPPBookButtonsSampleDelegate -- (void)didSelectPlaySample:(TPPBook *)book; +- (void)didSelectPlaySample:(TPPBook *_Null_unspecified)book; @end @protocol TPPBookDownloadCancellationDelegate -- (void)didSelectCancelForBookDetailDownloadingView:(TPPBookButtonsView *)view; -- (void)didSelectCancelForBookDetailDownloadFailedView:(TPPBookButtonsView *)failedView; +- (void)didSelectCancelForBookDetailDownloadingView:(TPPBookButtonsView *_Null_unspecified)view; +- (void)didSelectCancelForBookDetailDownloadFailedView:(TPPBookButtonsView *_Null_unspecified)failedView; @end @@ -30,14 +30,14 @@ /// because that's always identical and used in book cells and book detail views. @interface TPPBookButtonsView : UIView -@property (nonatomic, weak) TPPBook *book; +@property (nonatomic, weak) TPPBook *_Null_unspecified book; @property (nonatomic) TPPBookButtonsState state; -@property (nonatomic, weak) id delegate; -@property (nonatomic, weak) id downloadingDelegate; -@property (nonatomic, weak) id sampleDelegate; +@property (nonatomic, weak) id _Null_unspecified delegate; +@property (nonatomic, weak) id _Null_unspecified downloadingDelegate; +@property (nonatomic, weak) id _Null_unspecified sampleDelegate; @property (nonatomic) BOOL showReturnButtonIfApplicable; -- (instancetype)initWithSamplesEnabled:(BOOL)samplesEnabled; +- (instancetype _Null_unspecified )initWithSamplesEnabled:(BOOL)samplesEnabled; - (void)configureForBookDetailsContext; @end diff --git a/Palace/Book/UI/TPPBookButtonsView.m b/Palace/Book/UI/TPPBookButtonsView.m index ff48408c0..98f2bf12b 100644 --- a/Palace/Book/UI/TPPBookButtonsView.m +++ b/Palace/Book/UI/TPPBookButtonsView.m @@ -92,6 +92,7 @@ - (instancetype)initWithSamplesEnabled:(BOOL)samplesEnabled object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { + #pragma unused(note) [self updateButtons]; }]]; diff --git a/Palace/Catalog/TPPCatalogNavigationController.m b/Palace/Catalog/TPPCatalogNavigationController.m index a9c42ebca..112b5d90b 100644 --- a/Palace/Catalog/TPPCatalogNavigationController.m +++ b/Palace/Catalog/TPPCatalogNavigationController.m @@ -206,7 +206,7 @@ - (void)viewDidAppear:(BOOL)animated __block NSURL *mainFeedUrl = [NSURL URLWithString:currentAccount.catalogUrl]; void (^completion)(void) = ^() { NSArray* accounts = [[AccountsManager sharedInstance] accounts:nil]; - int count = [accounts count]; + //int count = [accounts count]; [[TPPSettings sharedSettings] setAccountMainFeedURL:mainFeedUrl]; [UIApplication sharedApplication].delegate.window.tintColor = [TPPConfiguration mainColor]; diff --git a/Palace/Catalog/TPPCatalogSearchViewController.m b/Palace/Catalog/TPPCatalogSearchViewController.m index d7514ac43..7b60824ca 100644 --- a/Palace/Catalog/TPPCatalogSearchViewController.m +++ b/Palace/Catalog/TPPCatalogSearchViewController.m @@ -211,6 +211,7 @@ - (void)catalogUngroupedFeed:(__unused TPPCatalogUngroupedFeed *)catalogUngroupe // Debounce timer reduces content flickering on each reload if (!self.debounceTimer) { self.debounceTimer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:NO block:^(NSTimer * _Nonnull timer) { + #pragma unused(timer) [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; self.debounceTimer = nil; }]; diff --git a/Palace/EkirjastoConfig/beta_Ekirjasto_Catalog_Feed.json b/Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_beta.json similarity index 100% rename from Palace/EkirjastoConfig/beta_Ekirjasto_Catalog_Feed.json rename to Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_beta.json diff --git a/Palace/EkirjastoConfig/Test_Catalog_Feed.json b/Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_dev.json similarity index 100% rename from Palace/EkirjastoConfig/Test_Catalog_Feed.json rename to Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_dev.json diff --git a/Palace/EkirjastoConfig/ellibs_Ekirjasto_Catalog_Feed.json b/Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_ellibs.json similarity index 100% rename from Palace/EkirjastoConfig/ellibs_Ekirjasto_Catalog_Feed.json rename to Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_ellibs.json diff --git a/Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed.json b/Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_production.json similarity index 100% rename from Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed.json rename to Palace/EkirjastoConfig/Ekirjasto_Catalog_Feed_production.json diff --git a/Palace/EkirjastoConfig/dev_Ekirjasto_Catalog_Feed.json b/Palace/EkirjastoConfig/TestLogin_Catalog_Feed.json similarity index 100% rename from Palace/EkirjastoConfig/dev_Ekirjasto_Catalog_Feed.json rename to Palace/EkirjastoConfig/TestLogin_Catalog_Feed.json diff --git a/Palace/EkirjastoConfig/prod_Ekirjasto_Catalog_Feed.json b/Palace/EkirjastoConfig/prod_Ekirjasto_Catalog_Feed.json deleted file mode 100644 index 1aa8db214..000000000 --- a/Palace/EkirjastoConfig/prod_Ekirjasto_Catalog_Feed.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "catalogs": [ - { - "links": [ - { - "href": "https://lib.e-kirjasto.fi/groups/", - "type": "application/atom+xml;profile=opds-catalog;kind=acquisition", - "rel": "http://opds-spec.org/catalog" - }, - { - "href": "https://lib.e-kirjasto.fi/groups/", - "rel": "start" - }, - { - "href": "https://lib.e-kirjasto.fi/groups/", - "rel": "self" - }, - { - "href": "https://lib.e-kirjasto.fi/authentication_document", - "type": "application/vnd.opds.authentication.v1.0+json" - }, - { - "href": "https://openebooks.net/", - "type": "text/html", - "rel": "alternate" - }, - { - "href": "https://e-kirjasto.ewl.epress.fi/", - "rel": "digital_magazines" - }, - { - "href": "https://librarysimplified.org/licenses/", - "type": "text/html", - "rel": "license" - }, - { - "href": "https://lib.e-kirjasto.fi/palaute", - "rel": "help" - } - ], - "metadata": { - "updated": "2024-04-15T07:24:51Z", - "description": "E-kirjaston kokoelma", - "id": "urn:uuid:8b7292e9-ed77-480e-a695-423f715be0f2", - "title": "E-kirjaston kokoelma" - } - } - ], - "links": [ - { - "href": "https://lib.e-kirjasto.fi/", - "type": "application/opds+json", - "rel": "self" - } - ], - "metadata": { - "title": "E-kirjasto" - } -} diff --git a/Palace/PDF/Model/TPPEncryptedPDFDataProvider.m b/Palace/PDF/Model/TPPEncryptedPDFDataProvider.m index ecca7903e..c4e40c0ac 100644 --- a/Palace/PDF/Model/TPPEncryptedPDFDataProvider.m +++ b/Palace/PDF/Model/TPPEncryptedPDFDataProvider.m @@ -22,10 +22,12 @@ @implementation TPPEncryptedPDFDataProvider } static void releaseData(void *info, const void *pointer) { + #pragma unused(info) free(pointer); } static size_t bytesAtPosition(void *info, void *buffer, off_t pos, size_t n) { + #pragma unused(info) NSUInteger start = pos; NSUInteger end = pos + n; NSData *data = _decryptor(_encryptedData, start, end); diff --git a/Palace/Utilities/Localization/Transifex/TransifexManager.swift b/Palace/Utilities/Localization/Transifex/TransifexManager.swift index e4421d2a9..116e1599f 100644 --- a/Palace/Utilities/Localization/Transifex/TransifexManager.swift +++ b/Palace/Utilities/Localization/Transifex/TransifexManager.swift @@ -6,6 +6,7 @@ // Copyright © 2022 The Palace Project. All rights reserved. // +import Foundation import Transifex class CustomLocaleProvider : TXCurrentLocaleProvider { @@ -16,12 +17,14 @@ class CustomLocaleProvider : TXCurrentLocaleProvider { @objc class TransifexManager: NSObject { @objc static func setup() { + let appLanguages = "en,fi,sv" let locales = TXLocaleState(sourceLocale: "en", - appLocales: ["en", "fi", "sv"], + appLocales: appLanguages.components(separatedBy: ","), currentLocaleProvider: CustomLocaleProvider()) TXNative.initialize( locales: locales, + // TODO:SAMI: Move the token to a config file token: "" ) diff --git a/Palace/Utilities/Localization/Transifex/txstrings.json b/Palace/Utilities/Localization/Transifex/txstrings.json index 71e61def7..5de58fac2 100644 --- a/Palace/Utilities/Localization/Transifex/txstrings.json +++ b/Palace/Utilities/Localization/Transifex/txstrings.json @@ -1 +1,3257 @@ -{"fi":{"If you sign out without enabling Sync, your books and any saved bookmarks will be removed.":{"string":"Jos kirjaudut ulos ottamatta synkronointia käyttöön, kirjasi ja tallennetut kirjanmerkkisi poistetaan."},"day_suffix_long":{"string":"{???, plural, one {1 päivä} other {%d päivää}}"},"year_suffix_short":{"string":"{???, plural, one {1 v} other {%d v}}"},"The page could not load due to a connection error.":{"string":"Sivua ei voitu ladata yhteysvirheen vuoksi."},"Remove Reservation":{"string":"Poista varaus"},"Categories":{"string":"Luokat"},"View sample for %@":{"string":"Katso näyte kohteesta %@"},"%@ version %@ (%@)":{"string":"%1$@ versio %2$@ (%3$@)"},"You must enable camera access for this application in order to sign up for a library card.":{"string":"Sinun on sallittava kameran käyttö tässä sovelluksessa, jotta voit rekisteröityä kirjastokortin käyttäjäksi."},"%d minutes and %d seconds":{"string":"%1$d minuuttia ja %2$d sekuntia"},"Testing":{"string":"Testaus"},"Author":{"string":"Tekijä"},"Download":{"string":"Lataa"},"Would you like to return it?":{"string":"Haluatko palauttaa sen?"},"End of Chapter":{"string":"Luvun loppu"},"Salasana unohtunut?":{"string":"Salasana unohtunut?"},"ePub":{"string":"ePub"},"month_suffix_long":{"string":"{???, plural, one {1 kuukausi} other {%d kuukautta}}"},"Bookmark added":{"string":"Kirjanmerkki lisättiin"},"The page could not load due to a conection error.":{"string":"Sivua ei voitu ladata yhteysvirheen vuoksi"},"%@%":{"string":"%1$@%2$"},"Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":"Haluatko varmasti poistaa teoksen %@ varauksistasi? Sen jälkeen et enää jonota tätä kirjaa."},"Downloading: %@%%":{"string":"Ladataan: %@%%"},"Listen":{"string":"Kuuntele"},"You have disabled location services for this app.":{"string":"Olet poistanut sijaintipalvelut käytöstä tämän sovelluksen kohdalla."},"Reserve":{"string":"Varaa"},"Thank You":{"string":"Kiitos"},"Reload":{"string":"Lataa uudelleen"},"Find Your Library":{"string":"Etsi kirjastosi"},"Unable to load PDF file":{"string":"PDF-tiedostoa ei voitu ladata"},"No email account is set for this device.":{"string":"Tälle laitteelle ei ole määritetty sähköpostitiliä."},"Download Error":{"string":"Latausvirhe"},"An error occurred during the authentication process":{"string":"Todennusprosessin aikana tapahtui virhe"},"Reached the end of the results.":{"string":"Päästiin tulosten loppuun."},"Under 13":{"string":"Alle 13"},"Reject":{"string":"Hylkää"},"Rewind %d seconds":{"string":"Kelaa taaksepäin %d sekuntia"},"Sync Listening Position":{"string":"Synkronoi kuuntelukohta"},"Please enter your birth year":{"string":"Anna syntymävuotesi"},"Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?":{"string":"Kirjanmerkkejäsi ja lukukohtiasi tallennetaan parhaillaan palvelimelle. Haluatko keskeyttää sen ja jatkaa uloskirjautumista?"},"%d hours and %d minutes":{"string":"%1$d tuntia ja %2$d minuuttia"},"%d hours and %d minute":{"string":"%1$d tuntia ja %2$d minuutti"},"My Books":{"string":"Omat kirjat"},"Signing out":{"string":"Kirjaudutaan ulos"},"Holds %@":{"string":"Pitää %@"},"Save the current location bookmark for later listening.":{"string":"Tallenna tämänhetkinen sijainti kirjanmerkiksi myöhempää kuuntelua varten."},"Sans font":{"string":"Sans-fontti"},"1.0× (Normal)":{"string":"1.0× (normaali)"},"Libraries":{"string":"Kirjastot"},"More...":{"string":"Lisää..."},"If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing.":{"string":"Jos toinen laite on käytettävissä, lähetä ääni Bluetoothin tai Airplayn kautta. Muussa tapauksessa älä tee mitään."},"13 or Older":{"string":"13 tai vanhempi"},"Verifying":{"string":"Vahvistetaan"},"Create Card":{"string":"Luo kortti"},"%02d min remaining":{"string":"%02d min jäljellä"},"\nYou are %ld in line for %ld copies.":{"string":"\nOlet sijalla %1$ld jonossa %2$ld teoksen osalta."},"30 Minutes":{"string":"30 minuuttia"},"AccessibilitySwitchLibrary":{"string":"AccessibilitySwitchLibrary"},"Downloading":{"string":"Ladataan"},"60 Minutes":{"string":"60 minuuttia"},"Unable to load the web page at this time.":{"string":"Verkkosivua ei voida ladata tällä hetkellä."},"An unknown error occurred. Please check your connection or try again later.":{"string":"Tapahtui tuntematon virhe. Tarkista internetyhteys tai yritä myöhemmin uudelleen."},"A bookmark has already been saved at this location.":{"string":"Tähän kohtaan on jo tallennettu kirjanmerkki."},"This book is available to borrow.":{"string":"Tämän kirjan voi lainata."},"Login Failed":{"string":"Sisäänkirjautuminen epäonnistui"},"Are you sure you want to return \"%@\"?":{"string":"Haluatko varmasti palauttaa teoksen %@?"},"Opens %@ for reading":{"string":"Avaa teoksen %@ lukemista varten"},"OK":{"string":"OK"},"Error Loading Library":{"string":"Virhe kirjaston lataamisessa"},"Software Licenses":{"string":"Ohjelmistolisenssit"},"Sync Reading Position":{"string":"Synkronoi lukukohta"},"More":{"string":"Lisää"},"Hide Barcode":{"string":"Piilota viivakoodi"},"Do you want to move to the page on which you left off?":{"string":"Haluatko siirtyä sivulle, jolle jäit?"},"Add Bookmark":{"string":"Lisää kirjanmerkki"},"Audiobook":{"string":"Äänikirja"},"There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later.":{"string":"Yhteyden muodostamisessa palvelimeen oli ongelma.\nVarmista, että internetyhteytesi toimii, tai yritä myöhemmin uudelleen."},"Resume":{"string":"Jatka"},"BrightnessSlider":{"string":"BrightnessSlider"},"Select a chapter or track from a list.":{"string":"Valitse luku tai kappale listalta."},"GCDAsyncSocketReadMaxedOutError":{"string":"Lukutoiminto saavutti asetetun enimmäispituuden"},"Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":"Haluatko varmasti poistaa teoksen %@ varauksistasi? Sen jälkeen et enää jonota tätä kirjaa."},"Remove Bookmark":{"string":"Poista kirjanmerkki"},"Privacy Policy":{"string":"Tietosuojakäytäntö"},"Rekisteröidy palveluun":{"string":"Rekisteröidy palveluun"},"%d hour and %d minutes":{"string":"%1$d tunti ja %2$d minuuttia"},"%@ through chapter":{"string":"%@ luvusta"},"DecreaseFontSize":{"string":"DecreaseFontSize"},"1.0×":{"string":"1.0×"},"It will expire in %@.":{"string":"Se vanhenee seuraavan ajan kuluttua: %@."},"%02dmin":{"string":"%02dmin"},"Please wait a moment before switching library accounts":{"string":"Odota hetki ennen kuin vaihdat kirjastotiliä"},"PIN":{"string":"PIN"},"An error was encountered while trying to open this book.":{"string":"Kirjaa avattaessa tapahtui virhe."},"week_suffix_long":{"string":"{???, plural, one {1 viikko} other {%d viikkoa}}"},"Please contact %@ to report an issue.":{"string":"Ilmoita ongelmasta ottamalla yhteyttä %@."},"One and one quarter faster than normal speed.":{"string":"Yksi ja yksi neljäsosa normaalia nopeutta nopeammin."},"Currently Playing: %@":{"string":"Toistetaan parhaillaan: %@"},"Select Year":{"string":"Valitse vuosi"},"Error extracting encrypted PDF file":{"string":"Virhe salatun PDF-tiedoston purkamisessa"},"By signing in, you agree to the End User License Agreement.":{"string":"Kirjautumalla sisään hyväksyt loppukäyttäjän lisenssisopimuksen."},"Open dyslexic font":{"string":"Open dyslexic -fontti"},"Invalid Credentials":{"string":"Virheelliset kirjautumistiedot"},"Publisher":{"string":"Kustantaja"},"Stay":{"string":"Pysy"},"day_suffix_short":{"string":"{???, plural, one {1 pv} other {%d pv}}"},"Next":{"string":"Seuraava"},"Read":{"string":"Lue"},"Deletes %@":{"string":"Poistaa %@"},"%@ played. %@ remaining.":{"string":"%1$@ toistettu. %2$@ jäljellä."},"Sleep Timer":{"string":"Uniajastin"},"Failed to get current location. Please try again.":{"string":"Tämänhetkisen sijainnin hakeminen epäonnistui. Yritä uudelleen."},"Continue":{"string":"Jatka"},"1.50×":{"string":"1.50×"},"The item you are trying to open is not currently supported.":{"string":"Kohdetta, jota yrität avata, ei tueta tällä hetkellä."},"Contents":{"string":"Sisältö"},"Sample":{"string":"Näyte"},"About":{"string":"Tietoja"},"%d hours, %d minutes and %d seconds":{"string":"%1$d tuntia, %2$d minuuttia ja %3$d sekuntia"},"Do you want to move to the time on which you left off?":{"string":"Haluatko siirtyä kohtaan, johon jäit?"},"Playback Destination":{"string":"Toiston kohde"},"Sort By:":{"string":"Lajitteluperuste:"},"sec":{"string":"s"},"Barcode or Username":{"string":"Viivakoodi tai käyttäjänimi"},"Page %d of ":{"string":"Sivu %d\/ "},"Show Barcode":{"string":"Näytä viivakoodi"},"%@ (file %@ of %d)":{"string":"%1$@ (tiedosto %2$@\/%3$d)"},"Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works.":{"string":"Open eBooks tarjoaa ilmaisia kirjoja niitä eniten tarvitseville lapsille.\n\nKokoelmaan kuuluu tuhansia suosittuja ja palkittuja julkaisuja sekä satoja tekijänoikeuksista vapaita teoksia."},"<>":{"string":"<>"},"%d minutes":{"string":"%d minuuttia"},"%02d hr %02 dmin":{"string":"%1$d h %2$d min"},"There are no bookmarks for this book.":{"string":"Tässä kirjassa ei ole kirjanmerkkejä."},"User Agreement":{"string":"Käyttäjäsopimus"},"GCDAsyncSocketWriteTimeoutError":{"string":"Kirjoitustoiminto aikakatkaistiin"},"Sign In Error":{"string":"Kirjautumisvirhe"},"Report an Issue":{"string":"Ilmoita ongelmasta"},"%02d:%02d:%02d":{"string":"%1$d:%2$d:%3$d"},"The book you were trying to open is invalid.":{"string":"Kirja, jonka yritit avata, on virheellinen."},"GCDAsyncSocketConnectTimeoutError":{"string":"Yritys muodostaa yhteys isäntään aikakatkaistiin"},"%02d:%02d":{"string":"%1$d:%2$d"},"%@ %@":{"string":"%1$@ %2$@"},"Search My Books":{"string":"Hae Omista kirjoista"},"Puuttuvatko tunnukset?":{"string":"Puuttuvatko tunnukset?"},"About App":{"string":"Tietoja sovelluksesta"},"Title":{"string":"Nimi"},"Error":{"string":"Virhe"},"Settings":{"string":"Asetukset"},"month_suffix_short":{"string":"{???, plural, one {1 kk} other {%d kk}}"},"A Problem Has Occurred":{"string":"Ilmeni ongelma"},"%d second":{"string":"%d sekunti"},"If you sign out, your books and any saved bookmarks will be removed.":{"string":"Jos kirjaudut ulos, kirjasi ja tallennetut kirjanmerkkisi poistetaan."},"AVAILABLE FOR CHECKOUT":{"string":"LAINATTAVISSA"},"Authenticate to reveal your PIN.":{"string":"Tunnistaudu PIN-koodisi selvittämiseksi."},"Play Sample":{"string":"Toista näyte"},"Normal speed.":{"string":"Normaali nopeus."},"Requesting":{"string":"Pyydetään"},"Connection Failed":{"string":"Yhteyden muodostaminen epäonnistui"},"Sign out":{"string":"Kirjaudu ulos"},"Submit":{"string":"Lähetä"},"Done":{"string":"Valmis"},"More %@ books":{"string":"Lisää %@ kirjoja"},"You have already checked out this loan. You may need to refresh your My Books list to download the title.":{"string":"Olet jo lainannut tämän teoksen. Sinun on ehkä päivitettävä Omat kirjat -listasi, jotta voit ladata teoksen."},"IncreaseFontSize":{"string":"IncreaseFontSize"},"This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk.":{"string":"Tätä URL-osoitetta ei löydy. Sulje sovellus kokonaan ja lataa se uudelleen. Jos ongelma jatkuu, ota yhteyttä kirjastosi tukipalveluun."},"There are no results":{"string":"Ei hakutuloksia"},"(dateType.rawValue)_suffix_short":{"string":"(dateType.rawValue)_suffix_short"},"Bookmarks":{"string":"Kirjanmerkit"},"All licenses of this book are currently checked out.":{"string":"Kaikki tämän kirjan lisenssit on tällä hetkellä lainattu."},"Advanced":{"string":"Edistynyt"},"Remove":{"string":"Poista"},"%02d hr, %02d min remaining":{"string":"%1$d h, %2$d min jäljellä"},"Welcome to Open eBooks":{"string":"Tervetuloa Open eBooksiin"},"Error Changing Sync Setting":{"string":"Virhe synkronointiasetuksen muuttamisessa"},"Three quarters of normal speed. Slower.":{"string":"Kolme neljäsosaa normaalista nopeudesta. Hitaampi."},"Kirjaudu palveluun":{"string":"Kirjaudu palveluun"},"A":{"string":"A"},"Less than 1 min remaining":{"string":"Alle 1 min jäljellä"},"An error was encountered while parsing the server response.":{"string":"Palvelimen vastauksen jäsennyksessä havaittiin virhe."},"Retry":{"string":"Yritä uudelleen"},"Salasano unohtunut?":{"string":"Salasana unohtunut?"},"Information":{"string":"Tiedot"},"%@ remaining":{"string":"%@ jäljellä"},"Reservations":{"string":"Varaukset"},"You need to login to access the collection.":{"string":"Sinun on kirjauduttava sisään päästäksesi kokoelmaan."},"Your book has not yet been downloaded.":{"string":"Kirjaasi ei ole vielä ladattu."},"Cancel":{"string":"Peruuta"},"One and a half times faster than normal speed.":{"string":"Puolitoista kertaa normaalia nopeutta nopeammin."},"Pause":{"string":"Keskeytä"},"Track %@":{"string":"Kappale %@"},"Ready for Download":{"string":"Valmis ladattavaksi"},"Try Again":{"string":"Yritä uudelleen"},"hour_suffix_short":{"string":"{???, plural, one {1 h} other {%d h}}"},"Try force-quitting the app and repeat the sign-in process.":{"string":"Kokeile pakottaa sovelluksen sulkeminen ja toista sisäänkirjautumisprosessi."},"Location Recovery Error":{"string":"Sijainnin palautusvirhe"},"Your report will be reviewed as soon as possible.":{"string":"Ilmoituksesi tarkistetaan mahdollisimman pian."},"%@":{"string":"%@"},"Opens audiobook %@ for listening":{"string":"Avaa äänikirjan %@ kuuntelua varten"},"Check Connection":{"string":"Tarkista yhteys"},"Delete":{"string":"Poista"},"The book license has expired.":{"string":"Kirjan lisenssi on vanhentunut."},"ABCabc":{"string":"ABCabc"},"Reader settings":{"string":"Lukijan asetukset"},"The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation.":{"string":"Palace-sovellus vaatii kertaluonteisen sijainnin tarkistuksen kirjastopalvelualueesi vahvistamiseksi. Olet poistanut sijaintipalvelut käytöstä tämän sovelluksen kohdalla. Ota ne käyttöön valitsemalla alla oleva Avaa asetukset -painike. Jatka sen jälkeen kortin luomista."},"Read more":{"string":"Lue lisää"},"You are %ld in line.":{"string":"Olet jonossa sijalla %ld."},"Gets %@":{"string":"Hakee %@"},"week_suffix_short":{"string":"{???, plural, one {1 vk} other {%d vk}}"},"Check Out":{"string":"Lainaa"},"%d hour and %d minute":{"string":"%1$d tunti ja %2$d minuutti"},"If you are under 13, all content downloaded to My Books will be removed.":{"string":"Jos olet alle 13-vuotias, kaikki Omat kirjat -kohtaan ladattu sisältö poistetaan."},"The download could not be completed.\nScroll down to 'View Issues' to see details.":{"string":"Latausta ei voitu suorittaa loppuun.\nKatso tiedot selaamalla alaspäin kohtaan Näytä ongelmat."},"Book format:":{"string":"Kirjan tiedostomuoto:"},"When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download.":{"string":"Kun varaat kirjan luettelosta, se näkyy täällä. Katso täältä aika ajoin, onko kirjasi ladattavissa."},"Default book font":{"string":"Kirjan oletusfontti"},"Please try again later.":{"string":"Yritä myöhemmin uudelleen."},"Narrators":{"string":"Lukijat"},"We can’t get your library right now. Please close and reopen the app to try again.":{"string":"Emme pääse kirjastoosi tällä hetkellä. Yritä uudelleen sulkemalla sovellus ja avaamalla se uudelleen."},"Table of Contents":{"string":"Sisällysluettelo"},"Keep":{"string":"Säilytä"},"Table of contents and bookmarks":{"string":"Sisällysluettelo ja kirjanmerkit"},"Unable to contact the server because the URL for signing in is missing.":{"string":"Palvelimeen ei saada yhteyttä, koska sisäänkirjautumisen URL-osoite puuttuu."},"Internal Error, bookmark failed to save.":{"string":"Sisäinen virhe, kirjanmerkin tallennus epäonnistui."},"The download could not be completed.":{"string":"Latausta ei voitu suorittaa loppuun."},"Please check your username and password and try again.":{"string":"Tarkista käyttäjänimesi ja salasanasi, ja yritä uudelleen."},"Delete Server Data":{"string":"Poista palvelimen tiedot"},"Your book is ready to read!":{"string":"Kirjasi on valmis luettavaksi!"},"Cancels hold for %@":{"string":"Peruuttaa kohteen %@ pidon"},"hour_suffix_long":{"string":"{???, plural, one {1 tunti} other {%d tuntia}}"},"Sync Bookmarks":{"string":"Synkronoi kirjanmerkit"},"Age Verification":{"string":"Iän vahvistus"},"Next Chapter":{"string":"Seuraava luku"},"The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu.":{"string":"DRM-kirjastolla kestää odotettua kauemmin. Odota ja yritä myöhemmin uudelleen.\n\nJos ongelma jatkuu, kokeile kirjautua ulos ja uudelleen sisään Kirjaston asetukset -valikosta."},"0.75×":{"string":"0.75×"},"15 Minutes":{"string":"15 minuuttia"},"%@ until playback pauses":{"string":"%@ kunnes toisto keskeytyy"},"Account":{"string":"Tili"},"Wait":{"string":"Odota"},"Play":{"string":"Toista"},"Returns %@":{"string":"Palauttaa %@"},"Corrupted Audiobook":{"string":"Vioittunut äänikirja"},"Distributed by: ":{"string":"Jakelija:"},"GCDAsyncSocketReadTimeoutError":{"string":"Lukutoiminto aikakatkaistiin"},"Authentication Required":{"string":"Todennus vaaditaan"},"We're sorry. Our sign up system is currently down. Please try again later.":{"string":"Olemme pahoillamme. Kirjautumisjärjestelmämme on tällä hetkellä poissa käytöstä. Yritä myöhemmin uudelleen."},"User denied location access. Go to system settings to enable location access for the Palace App.":{"string":"Käyttäjä kielsi sijaintitietojen käytön. Siirry järjestelmän asetuksiin ja ota sijaintitiedot käyttöön Palace-sovelluksessa."},"Unsupported Item":{"string":"Kohdetta ei tueta"},"Please wait":{"string":"Odota"},"Black on sepia text":{"string":"Musta teksti seepialla"},"The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information.":{"string":"Palace-sovellus vaatii kertaluonteisen sijainnin tarkistuksen kirjastopalvelualueesi vahvistamiseksi. Kun valitset Luo kortti, valitse ponnahdusikkunassa Salli kerran, jotta voimme vahvistaa tämän tiedon."},"Book Cover":{"string":"Kirjan kansi"},"This reservation will be automatically cancelled in %@.":{"string":"Tämä varaus peruutetaan automaattisesti seuraavan ajan kuluttua: %@."},"Close":{"string":"Sulje"},"(book.title) is an Adobe PDF, which is not supported.":{"string":"(book.title) on Adobe PDF -tiedosto, jota ei tueta."},"Downloads %@":{"string":"Lataa %@"},"Visit the Catalog to\nadd books to My Books.":{"string":"Siirry luetteloon ja\nlisää kirjoja Omiin kirjoihin."},"Borrowing %@ could not be completed.":{"string":"Teoksen %@ lainausta ei voitu suorittaa loppuun."},"Serif font":{"string":"Serif-fontti"},"Camera Access Disabled":{"string":"Kameran käyttöoikeus estetty"},"You are %ld in line for %ld copies.":{"string":"Olet sijalla %1$ld jonossa %2$ld teoksen osalta."},"Borrow Failed":{"string":"Lainaus epäonnistui"},"Something went wrong with the Adobe DRM system":{"string":"Jokin meni pieleen Adoben DRM-järjestelmässä"},"Unsupported format":{"string":"Muotoa ei tueta"},"It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?":{"string":"Näyttää siltä, että sinulla saattaa olla kirjan lataus tai palautus käynnissä. Haluatko keskeyttää sen ja jatkaa uloskirjautumista?"},"Acknowledgements":{"string":"Kiitokset"},"Show":{"string":"Näytä"},"Save your reading position and bookmarks to all your other devices.":{"string":"Tallenna lukukohtasi ja kirjanmerkkisi kaikkiin muihin laitteisiisi."},"Sign in":{"string":"Kirjaudu sisään"},"Load error. Please try signing out, then log in again.":{"string":"Latausvirhe. Kokeile kirjautua ulos ja sitten uudelleen sisään."},"Cancels the download for the current book: %@":{"string":"Peruuttaa nykyisen kirjan latauksen: %@"},"Table of contents":{"string":"Sisällysluettelo"},"The book you were trying to read is in an unsupported format.":{"string":"Yritit lukea kirjaa, jonka muotoa ei tueta."},"Content Licenses":{"string":"Sisältölisenssit"},"Browse Books":{"string":"Selaa kirjoja"},"Please wait...":{"string":"Odota..."},"WAITING FOR AVAILABILITY":{"string":"ODOTETAAN SAATAVUUTTA"},"Your Audiobook Has Finished":{"string":"Äänikirjasi on päättynyt"},"Back":{"string":"Takaisin"},"The audiobook you are trying to open appears to be corrupted. Try downloading it again.":{"string":"Äänikirja, jota yrität avata, vaikuttaa olevan vioittunut. Kokeile ladata se uudelleen."},"Category":{"string":"Luokka"},"PDF":{"string":"PDF"},"The return of %@ could not be completed.":{"string":"Teoksen %@ palautusta ei voitu suorittaa loppuun."},"Search":{"string":"Haku"},"Aa":{"string":"Aa"},"Downloading:":{"string":"Ladataan:"},"Authentication Expired":{"string":"Todennus vanhentunut"},"Request New Codes":{"string":"Pyydä uusia koodeja"},"Add Library":{"string":"Lisää kirjasto"},"Off":{"string":"Pois"},"(dateType.rawValue)_suffix_long":{"string":"(dateType.rawValue)_suffix_long"},"year_suffix_long":{"string":"{???, plural, one {1 vuosi} other {%d vuotta}}"},"Chapters":{"string":"Luvut"},"View Sample":{"string":"Katso näyte"},"The title you reserved, (book.title), is available.":{"string":"Varaamasi teos (book.title) on saatavilla."},"%d minute":{"string":"%d minuutti"},"1.25×":{"string":"1.25×"},"eCard":{"string":"eCard"},"White on black text":{"string":"Valkoinen teksti mustalla"},"Announcement":{"string":"Ilmoitus"},"The download for %@ could not be completed.":{"string":"Teoksen %@ latausta ei voitu suorittaa loppuun."},"The book you were trying to read is corrupted. Please try downloading it again.":{"string":"Kirja, jota yritit lukea, on vioittunut. Yritä ladata se uudelleen."},"Don't have a library card?":{"string":"Eikö sinulla ole kirjastokorttia?"},"Loading... Please wait.":{"string":"Ladataan... Odota."},"Duration":{"string":"Kesto"},"Fast Forward %d seconds":{"string":"Kelaa eteenpäin %d sekuntia"},"DRM Error":{"string":"DRM-virhe"},"Search Reservations":{"string":"Hae varauksista"},"Move":{"string":"Siirry"},"Description":{"string":"Kuvaus"},"Get":{"string":"Hae"},"Some books will be unavailable in this version. Please try updating to the latest version of the application.":{"string":"Jotkut kirjat eivät ole saatavilla tässä versiossa. Kokeile päivittää sovelluksen uusimpaan versioon."},"Cancels the failed download for this book: %@":{"string":"Peruuttaa tämän kirjan epäonnistuneen latauksen: %@"},"We're sorry. Currently we do not support signups for new patrons via the app.":{"string":"Emme valitettavasti tällä hetkellä tue uusien asiakkaiden rekisteröitymistä sovelluksen kautta."},"%d seconds":{"string":"%d sekuntia"},"Return":{"string":"Palauta"},"Published":{"string":"Julkaistu"},"Open Settings":{"string":"Avaa asetukset"},"Unkown error occurred. Please try again.":{"string":"Tapahtui tuntematon virhe. Yritä uudelleen."},"Selecting \"Delete\" will remove all bookmarks from the server for %@.":{"string":"Jos valitset Poista, kaikki teoksen %@ kirjanmerkit poistetaan palvelimelta."},"Your authentication details have expired. Please sign in again.":{"string":"Tunnistautumistietosi ovat vanhentuneet. Kirjaudu uudelleen sisään."},"Previous Chapter":{"string":"Edellinen luku"},"2.0×":{"string":"2.0×"},"GCDAsyncSocketClosedError":{"string":"Etäkumppani sulki yhteyden"},"%@ remaining in the book.":{"string":"%@ kirjaa jäljellä."},"Are you sure you want to delete \"%@\"?":{"string":"Haluatko varmasti poistaa teoksen %@?"},"An unknown error occurred while trying to sign out.":{"string":"Tuntematon virhe tapahtui, kun yritit kirjautua ulos."},"Playback Speed":{"string":"Toistonopeus"},"No Results Found":{"string":"Ei hakutuloksia"},"Please check your connection and try again.":{"string":"Tarkista internetyhteys ja yritä uudelleen."},"Two times normal speed. Fastest.":{"string":"Kaksi kertaa normaali nopeus. Nopein."},"currently":{"string":"tällä hetkellä"},"Accept":{"string":"Hyväksy"},"Retry the failed download for this book: %@":{"string":"Yritä ladata tämä kirja uudelleen: %@"},"Available for checkout in less than %@.":{"string":"Saatavilla lainattavaksi alle %@ kuluttua."},"Forgot your password?":{"string":"Unohditko salasanasi?"},"FAQ":{"string": "UKK"}},"sv":{"Forgot your password?":{"string":""},"day_suffix_long":{"string":""},"If you sign out without enabling Sync, your books and any saved bookmarks will be removed.":{"string":""},"The page could not load due to a connection error.":{"string":""},"Remove Reservation":{"string":""},"Categories":{"string":""},"View sample for %@":{"string":""},"%@ version %@ (%@)":{"string":""},"You must enable camera access for this application in order to sign up for a library card.":{"string":""},"%d minutes and %d seconds":{"string":""},"Testing":{"string":""},"Author":{"string":""},"Download":{"string":""},"Would you like to return it?":{"string":""},"End of Chapter":{"string":""},"Salasana unohtunut?":{"string":""},"ePub":{"string":""},"month_suffix_long":{"string":""},"Bookmark added":{"string":""},"The page could not load due to a conection error.":{"string":""},"%@%":{"string":""},"Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":""},"Listen":{"string":""},"Downloading: %@%%":{"string":""},"You have disabled location services for this app.":{"string":""},"Reserve":{"string":""},"Thank You":{"string":""},"Reload":{"string":""},"Find Your Library":{"string":""},"No email account is set for this device.":{"string":""},"Unable to load PDF file":{"string":""},"Download Error":{"string":""},"An error occurred during the authentication process":{"string":""},"Reached the end of the results.":{"string":""},"Under 13":{"string":""},"Reject":{"string":"Avvisa"},"Sync Listening Position":{"string":""},"Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?":{"string":""},"Please enter your birth year":{"string":""},"%d hours and %d minutes":{"string":""},"%d hours and %d minute":{"string":""},"Signing out":{"string":""},"My Books":{"string":"Mina böcker"},"Rewind %d seconds":{"string":""},"Holds %@":{"string":""},"Save the current location bookmark for later listening.":{"string":""},"Sans font":{"string":""},"1.0× (Normal)":{"string":"1,0× (Normal)"},"Libraries":{"string":""},"More...":{"string":""},"If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing.":{"string":""},"13 or Older":{"string":""},"Verifying":{"string":""},"Create Card":{"string":""},"%02d min remaining":{"string":""},"\nYou are %ld in line for %ld copies.":{"string":""},"30 Minutes":{"string":"30 minuter"},"Downloading":{"string":"Laddar ner"},"AccessibilitySwitchLibrary":{"string":""},"60 Minutes":{"string":""},"Unable to load the web page at this time.":{"string":""},"An unknown error occurred. Please check your connection or try again later.":{"string":"Det har uppstått ett okänt fel. Kontrollera din anslutning eller försök på nytt senare."},"A bookmark has already been saved at this location.":{"string":""},"This book is available to borrow.":{"string":"Denna bok är tillgänglig för utlåning."},"Login Failed":{"string":""},"Are you sure you want to return \"%@\"?":{"string":""},"Opens %@ for reading":{"string":""},"OK":{"string":""},"Software Licenses":{"string":""},"Error Loading Library":{"string":""},"Sync Reading Position":{"string":""},"More":{"string":""},"Hide Barcode":{"string":"Dölj streckkod"},"Do you want to move to the page on which you left off?":{"string":""},"Add Bookmark":{"string":"Lägg till bokmärke"},"Audiobook":{"string":""},"There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later.":{"string":""},"Resume":{"string":""},"BrightnessSlider":{"string":""},"Select a chapter or track from a list.":{"string":""},"GCDAsyncSocketReadMaxedOutError":{"string":""},"Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":"Är du säker att du vill ta bort \"%@\" från dina reservationer? Du kommer inte längre att stå i kö till denna bok."},"Remove Bookmark":{"string":""},"Privacy Policy":{"string":"Integritetspolicy"},"Rekisteröidy palveluun":{"string":""},"%d hour and %d minutes":{"string":""},"%@ through chapter":{"string":""},"DecreaseFontSize":{"string":""},"It will expire in %@.":{"string":""},"1.0×":{"string":""},"%02dmin":{"string":""},"Please wait a moment before switching library accounts":{"string":""},"PIN":{"string":""},"An error was encountered while trying to open this book.":{"string":"Det uppstod ett fel med att öppna boken."},"Error extracting encrypted PDF file":{"string":""},"Please contact %@ to report an issue.":{"string":""},"week_suffix_long":{"string":"{???, plural, one {1 vecka} other {%d veckor}}"},"One and one quarter faster than normal speed.":{"string":""},"Select Year":{"string":""},"Currently Playing: %@":{"string":""},"By signing in, you agree to the End User License Agreement.":{"string":""},"Open dyslexic font":{"string":"typsnittet OpenDyslexic"},"Invalid Credentials":{"string":""},"Publisher":{"string":""},"Stay":{"string":""},"day_suffix_short":{"string":""},"Next":{"string":""},"Read":{"string":""},"Deletes %@":{"string":""},"%@ played. %@ remaining.":{"string":""},"Sleep Timer":{"string":""},"Failed to get current location. Please try again.":{"string":""},"Continue":{"string":"Fortsätt"},"1.50×":{"string":""},"The item you are trying to open is not currently supported.":{"string":""},"Contents":{"string":""},"Sample":{"string":""},"About":{"string":""},"Do you want to move to the time on which you left off?":{"string":""},"Sort By:":{"string":""},"Playback Destination":{"string":""},"%d hours, %d minutes and %d seconds":{"string":""},"sec":{"string":""},"Barcode or Username":{"string":""},"Page %d of ":{"string":""},"%@ (file %@ of %d)":{"string":""},"%02d hr %02 dmin":{"string":"%1$d t %2$d min"},"<>":{"string":""},"Show Barcode":{"string":""},"%d minutes":{"string":""},"Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works.":{"string":""},"There are no bookmarks for this book.":{"string":""},"User Agreement":{"string":""},"GCDAsyncSocketWriteTimeoutError":{"string":""},"Report an Issue":{"string":"Rapportera ett problem"},"%02d:%02d:%02d":{"string":""},"Sign In Error":{"string":""},"The book you were trying to open is invalid.":{"string":""},"GCDAsyncSocketConnectTimeoutError":{"string":""},"%02d:%02d":{"string":"%1$d:%2$d"},"%@ %@":{"string":""},"Puuttuvatko tunnukset?":{"string":""},"Search My Books":{"string":""},"About App":{"string":""},"Error":{"string":""},"AVAILABLE FOR CHECKOUT":{"string":""},"Title":{"string":""},"month_suffix_short":{"string":""},"Settings":{"string":""},"%d second":{"string":"%d sekund"},"A Problem Has Occurred":{"string":""},"If you sign out, your books and any saved bookmarks will be removed.":{"string":""},"Normal speed.":{"string":""},"Authenticate to reveal your PIN.":{"string":""},"Play Sample":{"string":""},"Requesting":{"string":""},"Connection Failed":{"string":""},"Sign out":{"string":""},"Submit":{"string":""},"Done":{"string":""},"More %@ books":{"string":""},"You have already checked out this loan. You may need to refresh your My Books list to download the title.":{"string":""},"IncreaseFontSize":{"string":""},"There are no results":{"string":""},"This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk.":{"string":""},"(dateType.rawValue)_suffix_short":{"string":""},"Bookmarks":{"string":""},"All licenses of this book are currently checked out.":{"string":""},"Advanced":{"string":"Avancerat"},"Remove":{"string":"Ta bort"},"%02d hr, %02d min remaining":{"string":""},"Welcome to Open eBooks":{"string":""},"Error Changing Sync Setting":{"string":""},"Three quarters of normal speed. Slower.":{"string":""},"Kirjaudu palveluun":{"string":""},"A":{"string":""},"Less than 1 min remaining":{"string":""},"An error was encountered while parsing the server response.":{"string":""},"Retry":{"string":""},"Salasano unohtunut?":{"string":"Har du glömt ditt lösenord?"},"Information":{"string":"Information"},"%@ remaining":{"string":""},"Your book has not yet been downloaded.":{"string":""},"You need to login to access the collection.":{"string":""},"Cancel":{"string":""},"One and a half times faster than normal speed.":{"string":""},"Reservations":{"string":"Reservationer"},"Pause":{"string":""},"Track %@":{"string":""},"Ready for Download":{"string":""},"Your report will be reviewed as soon as possible.":{"string":""},"Try Again":{"string":""},"Try force-quitting the app and repeat the sign-in process.":{"string":""},"hour_suffix_short":{"string":""},"Location Recovery Error":{"string":""},"%@":{"string":""},"Opens audiobook %@ for listening":{"string":""},"Check Connection":{"string":""},"The book license has expired.":{"string":""},"Delete":{"string":""},"ABCabc":{"string":""},"Reader settings":{"string":""},"You are %ld in line.":{"string":""},"The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation.":{"string":"Palace-appen behöver kontrollera din position en gång för att verifiera ditt område för biblioteksservice. Du har inaktiverat positionstjänsten för denna app. För att aktivera den peka på knappen Öppna inställningar nedan för att fortsätta skapa kort."},"Read more":{"string":""},"week_suffix_short":{"string":""},"Gets %@":{"string":""},"Check Out":{"string":""},"%d hour and %d minute":{"string":"%1$d timme och %2$d minut"},"Book format:":{"string":"Bokformat:"},"The download could not be completed.\nScroll down to 'View Issues' to see details.":{"string":""},"If you are under 13, all content downloaded to My Books will be removed.":{"string":"Om du är under 13 år kommer allt innehåll som laddats ner i Mina böcker att raderas."},"When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download.":{"string":""},"Default book font":{"string":""},"Please try again later.":{"string":""},"Narrators":{"string":""},"We can’t get your library right now. Please close and reopen the app to try again.":{"string":""},"Table of Contents":{"string":""},"Keep":{"string":""},"Table of contents and bookmarks":{"string":""},"Unable to contact the server because the URL for signing in is missing.":{"string":""},"Internal Error, bookmark failed to save.":{"string":""},"Please check your username and password and try again.":{"string":""},"The download could not be completed.":{"string":""},"Delete Server Data":{"string":""},"Your book is ready to read!":{"string":""},"Cancels hold for %@":{"string":""},"hour_suffix_long":{"string":""},"Sync Bookmarks":{"string":""},"Age Verification":{"string":""},"Next Chapter":{"string":""},"The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu.":{"string":""},"0.75×":{"string":""},"15 Minutes":{"string":""},"%@ until playback pauses":{"string":""},"Account":{"string":""},"Wait":{"string":""},"Play":{"string":""},"Returns %@":{"string":""},"Corrupted Audiobook":{"string":""},"Distributed by: ":{"string":""},"We're sorry. Our sign up system is currently down. Please try again later.":{"string":""},"Authentication Required":{"string":""},"GCDAsyncSocketReadTimeoutError":{"string":""},"User denied location access. Go to system settings to enable location access for the Palace App.":{"string":""},"Unsupported Item":{"string":""},"Please wait":{"string":""},"Black on sepia text":{"string":"Svart text mot sepiabakgrund"},"The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information.":{"string":""},"Book Cover":{"string":""},"You are %ld in line for %ld copies.":{"string":""},"This reservation will be automatically cancelled in %@.":{"string":""},"(book.title) is an Adobe PDF, which is not supported.":{"string":"(book.title) är en Adobe PDF och stöds således inte."},"Downloads %@":{"string":""},"Visit the Catalog to\nadd books to My Books.":{"string":""},"Borrow Failed":{"string":"Det gick inte att låna"},"Borrowing %@ could not be completed.":{"string":""},"Serif font":{"string":""},"Camera Access Disabled":{"string":""},"Close":{"string":"Stäng"},"Something went wrong with the Adobe DRM system":{"string":""},"Unsupported format":{"string":""},"Show":{"string":""},"Acknowledgements":{"string":""},"It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?":{"string":""},"Save your reading position and bookmarks to all your other devices.":{"string":""},"Sign in":{"string":""},"Load error. Please try signing out, then log in again.":{"string":""},"Cancels the download for the current book: %@":{"string":""},"Table of contents":{"string":""},"The book you were trying to read is in an unsupported format.":{"string":""},"Content Licenses":{"string":""},"Browse Books":{"string":""},"Please wait...":{"string":""},"Back":{"string":""},"Your Audiobook Has Finished":{"string":""},"WAITING FOR AVAILABILITY":{"string":""},"The audiobook you are trying to open appears to be corrupted. Try downloading it again.":{"string":""},"Category":{"string":"Kategori"},"PDF":{"string":""},"The return of %@ could not be completed.":{"string":""},"Search":{"string":""},"Aa":{"string":"Aa"},"Downloading:":{"string":""},"Request New Codes":{"string":""},"Authentication Expired":{"string":""},"Add Library":{"string":""},"View Sample":{"string":""},"Off":{"string":""},"(dateType.rawValue)_suffix_long":{"string":"(dateType.rawValue)_suffix_long"},"Chapters":{"string":"Kapitel"},"year_suffix_long":{"string":""},"The title you reserved, (book.title), is available.":{"string":""},"%d minute":{"string":""},"1.25×":{"string":""},"eCard":{"string":""},"White on black text":{"string":""},"Announcement":{"string":""},"The download for %@ could not be completed.":{"string":""},"The book you were trying to read is corrupted. Please try downloading it again.":{"string":""},"Don't have a library card?":{"string":""},"Loading... Please wait.":{"string":""},"Duration":{"string":""},"Fast Forward %d seconds":{"string":""},"DRM Error":{"string":""},"Search Reservations":{"string":""},"Move":{"string":""},"Get":{"string":""},"Description":{"string":"Beskrivning"},"We're sorry. Currently we do not support signups for new patrons via the app.":{"string":""},"Cancels the failed download for this book: %@":{"string":""},"Some books will be unavailable in this version. Please try updating to the latest version of the application.":{"string":""},"%d seconds":{"string":""},"Return":{"string":""},"Published":{"string":""},"Open Settings":{"string":""},"Unkown error occurred. Please try again.":{"string":"Det har uppstått ett okänt fel. Försök på nytt."},"Selecting \"Delete\" will remove all bookmarks from the server for %@.":{"string":""},"Your authentication details have expired. Please sign in again.":{"string":"Dina autentiseringsuppgifter har löpt ut. Logga in på nytt."},"Previous Chapter":{"string":"Föregående kapitel"},"GCDAsyncSocketClosedError":{"string":""},"2.0×":{"string":"2,0×"},"%@ remaining in the book.":{"string":""},"Are you sure you want to delete \"%@\"?":{"string":""},"An unknown error occurred while trying to sign out.":{"string":""},"Playback Speed":{"string":""},"No Results Found":{"string":""},"Please check your connection and try again.":{"string":"Kontrollera din anslutning och försök på nytt."},"Two times normal speed. Fastest.":{"string":""},"currently":{"string":""},"Accept":{"string":""},"Retry the failed download for this book: %@":{"string":""},"year_suffix_short":{"string":""},"Available for checkout in less than %@.":{"string":""}},"en":{"Forgot your password?":{"string":"Forgot your password?"},"day_suffix_long":{"string":"{???, plural, one {1 day} other {%d days}}"},"If you sign out without enabling Sync, your books and any saved bookmarks will be removed.":{"string":"If you sign out without enabling Sync, your books and any saved bookmarks will be removed."},"The page could not load due to a connection error.":{"string":"The page could not load due to a connection error."},"Remove Reservation":{"string":"Remove Reservation"},"Categories":{"string":"Categories"},"View sample for %@":{"string":"View sample for %@"},"%@ version %@ (%@)":{"string":"%1$@ version %2$@ (%3$@)"},"You must enable camera access for this application in order to sign up for a library card.":{"string":"You must enable camera access for this application in order to sign up for a library card."},"%d minutes and %d seconds":{"string":"%1$d minutes and %2$d seconds"},"Testing":{"string":"Testing"},"Author":{"string":"Author"},"Download":{"string":"Download"},"Would you like to return it?":{"string":"Would you like to return it?"},"End of Chapter":{"string":"End of Chapter"},"Salasana unohtunut?":{"string":"Salasana unohtunut?"},"ePub":{"string":"ePub"},"month_suffix_long":{"string":"{???, plural, one {1 month} other {%d months}}"},"Bookmark added":{"string":"Bookmark added"},"The page could not load due to a conection error.":{"string":"The page could not load due to a conection error."},"%@%":{"string":"%1$@%2$"},"Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":"Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book."},"Listen":{"string":"Listen"},"Downloading: %@%%":{"string":"Downloading: %@%%"},"You have disabled location services for this app.":{"string":"You have disabled location services for this app."},"Reserve":{"string":"Reserve"},"Thank You":{"string":"Thank You"},"Reload":{"string":"Reload"},"Find Your Library":{"string":"Find Your Library"},"No email account is set for this device.":{"string":"No email account is set for this device."},"Unable to load PDF file":{"string":"Unable to load PDF file"},"Download Error":{"string":"Download Error"},"An error occurred during the authentication process":{"string":"An error occurred during the authentication process"},"Reached the end of the results.":{"string":"Reached the end of the results."},"Under 13":{"string":"Under 13"},"Reject":{"string":"Reject"},"Rewind %d seconds":{"string":"Rewind %d seconds"},"Sync Listening Position":{"string":"Sync Listening Position"},"Please enter your birth year":{"string":"Please enter your birth year"},"Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?":{"string":"Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?"},"%d hours and %d minutes":{"string":"%1$d hours and %2$d minutes"},"%d hours and %d minute":{"string":"%1$d hours and %2$d minute"},"My Books":{"string":"My Books"},"Signing out":{"string":"Signing out"},"Holds %@":{"string":"Holds %@"},"Save the current location bookmark for later listening.":{"string":"Save the current location bookmark for later listening."},"Sans font":{"string":"Sans font"},"1.0× (Normal)":{"string":"1.0× (Normal)"},"Libraries":{"string":"Libraries"},"More...":{"string":"More..."},"If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing.":{"string":"If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing."},"13 or Older":{"string":"13 or Older"},"Verifying":{"string":"Verifying"},"Create Card":{"string":"Create Card"},"%02d min remaining":{"string":"%02d min remaining"},"\nYou are %ld in line for %ld copies.":{"string":"\nYou are %1$ld in line for %2$ld copies."},"30 Minutes":{"string":"30 Minutes"},"Downloading":{"string":"Downloading"},"AccessibilitySwitchLibrary":{"string":"AccessibilitySwitchLibrary"},"60 Minutes":{"string":"60 Minutes"},"Unable to load the web page at this time.":{"string":"Unable to load the web page at this time."},"An unknown error occurred. Please check your connection or try again later.":{"string":"An unknown error occurred. Please check your connection or try again later."},"A bookmark has already been saved at this location.":{"string":"A bookmark has already been saved at this location."},"This book is available to borrow.":{"string":"This book is available to borrow."},"Login Failed":{"string":"Login Failed"},"Are you sure you want to return \"%@\"?":{"string":"Are you sure you want to return \"%@\"?"},"Opens %@ for reading":{"string":"Opens %@ for reading"},"OK":{"string":"OK"},"Software Licenses":{"string":"Software Licenses"},"Error Loading Library":{"string":"Error Loading Library"},"Sync Reading Position":{"string":"Sync Reading Position"},"More":{"string":"More"},"Hide Barcode":{"string":"Hide Barcode"},"Do you want to move to the page on which you left off?":{"string":"Do you want to move to the page on which you left off?"},"Add Bookmark":{"string":"Add Bookmark"},"Audiobook":{"string":"Audiobook"},"There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later.":{"string":"There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later."},"Resume":{"string":"Resume"},"BrightnessSlider":{"string":"BrightnessSlider"},"Select a chapter or track from a list.":{"string":"Select a chapter or track from a list."},"GCDAsyncSocketReadMaxedOutError":{"string":"Read operation reached set maximum length"},"Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book.":{"string":"Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book."},"Remove Bookmark":{"string":"Remove Bookmark"},"Privacy Policy":{"string":"Privacy Policy"},"Rekisteröidy palveluun":{"string":"Rekisteröidy palveluun"},"%d hour and %d minutes":{"string":"%1$d hour and %2$d minutes"},"%@ through chapter":{"string":"%@ through chapter"},"DecreaseFontSize":{"string":"DecreaseFontSize"},"It will expire in %@.":{"string":"It will expire in %@."},"1.0×":{"string":"1.0×"},"%02dmin":{"string":"%02dmin"},"Please wait a moment before switching library accounts":{"string":"Please wait a moment before switching library accounts"},"PIN":{"string":"PIN"},"An error was encountered while trying to open this book.":{"string":"An error was encountered while trying to open this book."},"Error extracting encrypted PDF file":{"string":"Error extracting encrypted PDF file"},"Please contact %@ to report an issue.":{"string":"Please contact %@ to report an issue."},"week_suffix_long":{"string":"{???, plural, one {1 week} other {%d weeks}}"},"One and one quarter faster than normal speed.":{"string":"One and one quarter faster than normal speed."},"Select Year":{"string":"Select Year"},"Currently Playing: %@":{"string":"Currently Playing: %@"},"By signing in, you agree to the End User License Agreement.":{"string":"By signing in, you agree to the End User License Agreement."},"Open dyslexic font":{"string":"Open dyslexic font"},"Invalid Credentials":{"string":"Invalid Credentials"},"Publisher":{"string":"Publisher"},"Stay":{"string":"Stay"},"day_suffix_short":{"string":"{???, plural, one {1 d} other {%d d}}"},"Next":{"string":"Next"},"Read":{"string":"Read"},"Deletes %@":{"string":"Deletes %@"},"%@ played. %@ remaining.":{"string":"%1$@ played. %2$@ remaining."},"Sleep Timer":{"string":"Sleep Timer"},"Failed to get current location. Please try again.":{"string":"Failed to get current location. Please try again."},"Continue":{"string":"Continue"},"1.50×":{"string":"1.50×"},"The item you are trying to open is not currently supported.":{"string":"The item you are trying to open is not currently supported."},"Contents":{"string":"Contents"},"Sample":{"string":"Sample"},"About":{"string":"About"},"Do you want to move to the time on which you left off?":{"string":"Do you want to move to the time on which you left off?"},"Sort By:":{"string":"Sort By:"},"Playback Destination":{"string":"Playback Destination"},"%d hours, %d minutes and %d seconds":{"string":"%1$d hours, %2$d minutes and %3$d seconds"},"sec":{"string":"sec"},"Barcode or Username":{"string":"Barcode or Username"},"Page %d of ":{"string":"Page %d of "},"%@ (file %@ of %d)":{"string":"%1$@ (file %2$@ of %3$d)"},"%02d hr %02 dmin":{"string":"%1$d hr %2$d min"},"<>":{"string":"<>"},"Show Barcode":{"string":"Show Barcode"},"%d minutes":{"string":"%d minutes"},"Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works.":{"string":"Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works."},"There are no bookmarks for this book.":{"string":"There are no bookmarks for this book."},"User Agreement":{"string":"User Agreement"},"GCDAsyncSocketWriteTimeoutError":{"string":"Write operation timed out"},"Report an Issue":{"string":"Report an Issue"},"%02d:%02d:%02d":{"string":"%1$d:%2$d:%3$d"},"Sign In Error":{"string":"Sign In Error"},"The book you were trying to open is invalid.":{"string":"The book you were trying to open is invalid."},"GCDAsyncSocketConnectTimeoutError":{"string":"Attempt to connect to host timed out"},"%02d:%02d":{"string":"%1$d:%2$d"},"%@ %@":{"string":"%1$@ %2$@"},"Puuttuvatko tunnukset?":{"string":"Puuttuvatko tunnukset?"},"Search My Books":{"string":"Search My Books"},"About App":{"string":"About App"},"Error":{"string":"Error"},"AVAILABLE FOR CHECKOUT":{"string":"AVAILABLE FOR CHECKOUT"},"Title":{"string":"Title"},"month_suffix_short":{"string":"{???, plural, one {1 m} other {%d m}}"},"Settings":{"string":"Settings"},"%d second":{"string":"%d second"},"A Problem Has Occurred":{"string":"A Problem Has Occurred"},"If you sign out, your books and any saved bookmarks will be removed.":{"string":"If you sign out, your books and any saved bookmarks will be removed."},"Normal speed.":{"string":"Normal speed."},"Authenticate to reveal your PIN.":{"string":"Authenticate to reveal your PIN."},"Play Sample":{"string":"Play Sample"},"Requesting":{"string":"Requesting"},"Connection Failed":{"string":"Connection Failed"},"Sign out":{"string":"Sign out"},"Submit":{"string":"Submit"},"Done":{"string":"Done"},"More %@ books":{"string":"More %@ books"},"You have already checked out this loan. You may need to refresh your My Books list to download the title.":{"string":"You have already checked out this loan. You may need to refresh your My Books list to download the title."},"IncreaseFontSize":{"string":"IncreaseFontSize"},"There are no results":{"string":"There are no results"},"This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk.":{"string":"This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk."},"(dateType.rawValue)_suffix_short":{"string":"(dateType.rawValue)_suffix_short"},"Bookmarks":{"string":"Bookmarks"},"All licenses of this book are currently checked out.":{"string":"All licenses of this book are currently checked out."},"Advanced":{"string":"Advanced"},"Remove":{"string":"Remove"},"%02d hr, %02d min remaining":{"string":"%1$d hr, %2$d min remaining"},"Welcome to Open eBooks":{"string":"Welcome to Open eBooks"},"Error Changing Sync Setting":{"string":"Error Changing Sync Setting"},"Three quarters of normal speed. Slower.":{"string":"Three quarters of normal speed. Slower."},"Kirjaudu palveluun":{"string":"Kirjaudu palveluun"},"A":{"string":"A"},"Less than 1 min remaining":{"string":"Less than 1 min remaining"},"An error was encountered while parsing the server response.":{"string":"An error was encountered while parsing the server response."},"Retry":{"string":"Retry"},"Salasano unohtunut?":{"string":"Salasano unohtunut?"},"Information":{"string":"Information"},"%@ remaining":{"string":"%@ remaining"},"Your book has not yet been downloaded.":{"string":"Your book has not yet been downloaded."},"You need to login to access the collection.":{"string":"You need to login to access the collection."},"Cancel":{"string":"Cancel"},"One and a half times faster than normal speed.":{"string":"One and a half times faster than normal speed."},"Reservations":{"string":"Reservations"},"Pause":{"string":"Pause"},"Track %@":{"string":"Track %@"},"Ready for Download":{"string":"Ready for Download"},"Your report will be reviewed as soon as possible.":{"string":"Your report will be reviewed as soon as possible."},"Try Again":{"string":"Try Again"},"Try force-quitting the app and repeat the sign-in process.":{"string":"Try force-quitting the app and repeat the sign-in process."},"hour_suffix_short":{"string":"{???, plural, one {1 h} other {%d h}}"},"Location Recovery Error":{"string":"Location Recovery Error"},"%@":{"string":"%@"},"Opens audiobook %@ for listening":{"string":"Opens audiobook %@ for listening"},"Check Connection":{"string":"Check Connection"},"The book license has expired.":{"string":"The book license has expired."},"Delete":{"string":"Delete"},"ABCabc":{"string":"ABCabc"},"Reader settings":{"string":"Reader settings"},"You are %ld in line.":{"string":"You are %ld in line."},"The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation.":{"string":"The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation."},"Read more":{"string":"Read more"},"week_suffix_short":{"string":"{???, plural, one {1 w} other {%d w}}"},"Gets %@":{"string":"Gets %@"},"Check Out":{"string":"Check Out"},"%d hour and %d minute":{"string":"%1$d hour and %2$d minute"},"Book format:":{"string":"Book format:"},"The download could not be completed.\nScroll down to 'View Issues' to see details.":{"string":"The download could not be completed.\nScroll down to 'View Issues' to see details."},"If you are under 13, all content downloaded to My Books will be removed.":{"string":"If you are under 13, all content downloaded to My Books will be removed."},"When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download.":{"string":"When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download."},"Default book font":{"string":"Default book font"},"Please try again later.":{"string":"Please try again later."},"Narrators":{"string":"Narrators"},"We can’t get your library right now. Please close and reopen the app to try again.":{"string":"We can’t get your library right now. Please close and reopen the app to try again."},"Table of Contents":{"string":"Table of Contents"},"Keep":{"string":"Keep"},"Table of contents and bookmarks":{"string":"Table of contents and bookmarks"},"Unable to contact the server because the URL for signing in is missing.":{"string":"Unable to contact the server because the URL for signing in is missing."},"Internal Error, bookmark failed to save.":{"string":"Internal Error, bookmark failed to save."},"Please check your username and password and try again.":{"string":"Please check your username and password and try again."},"The download could not be completed.":{"string":"The download could not be completed."},"Delete Server Data":{"string":"Delete Server Data"},"Your book is ready to read!":{"string":"Your book is ready to read!"},"Cancels hold for %@":{"string":"Cancels hold for %@"},"hour_suffix_long":{"string":"{???, plural, one {1 hour} other {%d hours}}"},"Sync Bookmarks":{"string":"Sync Bookmarks"},"Age Verification":{"string":"Age Verification"},"Next Chapter":{"string":"Next Chapter"},"The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu.":{"string":"The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu."},"0.75×":{"string":"0.75×"},"15 Minutes":{"string":"15 Minutes"},"%@ until playback pauses":{"string":"%@ until playback pauses"},"Account":{"string":"Account"},"Wait":{"string":"Wait"},"Play":{"string":"Play"},"Returns %@":{"string":"Returns %@"},"Corrupted Audiobook":{"string":"Corrupted Audiobook"},"Distributed by: ":{"string":"Distributed by: "},"We're sorry. Our sign up system is currently down. Please try again later.":{"string":"We're sorry. Our sign up system is currently down. Please try again later."},"Authentication Required":{"string":"Authentication Required"},"GCDAsyncSocketReadTimeoutError":{"string":"Read operation timed out"},"User denied location access. Go to system settings to enable location access for the Palace App.":{"string":"User denied location access. Go to system settings to enable location access for the Palace App."},"Unsupported Item":{"string":"Unsupported Item"},"Please wait":{"string":"Please wait"},"Black on sepia text":{"string":"Black on sepia text"},"The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information.":{"string":"The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information."},"Book Cover":{"string":"Book Cover"},"You are %ld in line for %ld copies.":{"string":"You are %1$ld in line for %2$ld copies."},"This reservation will be automatically cancelled in %@.":{"string":"This reservation will be automatically cancelled in %@."},"(book.title) is an Adobe PDF, which is not supported.":{"string":"(book.title) is an Adobe PDF, which is not supported."},"Downloads %@":{"string":"Downloads %@"},"Visit the Catalog to\nadd books to My Books.":{"string":"Visit the Catalog to\nadd books to My Books."},"Borrow Failed":{"string":"Borrow Failed"},"Borrowing %@ could not be completed.":{"string":"Borrowing %@ could not be completed."},"Serif font":{"string":"Serif font"},"Camera Access Disabled":{"string":"Camera Access Disabled"},"Close":{"string":"Close"},"Something went wrong with the Adobe DRM system":{"string":"Something went wrong with the Adobe DRM system"},"Unsupported format":{"string":"Unsupported format"},"Show":{"string":"Show"},"Acknowledgements":{"string":"Acknowledgements"},"It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?":{"string":"It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?"},"Save your reading position and bookmarks to all your other devices.":{"string":"Save your reading position and bookmarks to all your other devices."},"Sign in":{"string":"Sign in"},"Load error. Please try signing out, then log in again.":{"string":"Load error. Please try signing out, then log in again."},"Cancels the download for the current book: %@":{"string":"Cancels the download for the current book: %@"},"Table of contents":{"string":"Table of contents"},"The book you were trying to read is in an unsupported format.":{"string":"The book you were trying to read is in an unsupported format."},"Content Licenses":{"string":"Content Licenses"},"Browse Books":{"string":"Browse Books"},"Please wait...":{"string":"Please wait..."},"Back":{"string":"Back"},"Your Audiobook Has Finished":{"string":"Your Audiobook Has Finished"},"WAITING FOR AVAILABILITY":{"string":"WAITING FOR AVAILABILITY"},"The audiobook you are trying to open appears to be corrupted. Try downloading it again.":{"string":"The audiobook you are trying to open appears to be corrupted. Try downloading it again."},"Category":{"string":"Category"},"PDF":{"string":"PDF"},"The return of %@ could not be completed.":{"string":"The return of %@ could not be completed."},"Search":{"string":"Search"},"Aa":{"string":"Aa"},"Downloading:":{"string":"Downloading:"},"Request New Codes":{"string":"Request New Codes"},"Authentication Expired":{"string":"Authentication Expired"},"Add Library":{"string":"Add Library"},"View Sample":{"string":"View Sample"},"Off":{"string":"Off"},"(dateType.rawValue)_suffix_long":{"string":"(dateType.rawValue)_suffix_long"},"Chapters":{"string":"Chapters"},"year_suffix_long":{"string":"{???, plural, one {1 year} other {%d years}}"},"The title you reserved, (book.title), is available.":{"string":"The title you reserved, (book.title), is available."},"%d minute":{"string":"%d minute"},"1.25×":{"string":"1.25×"},"eCard":{"string":"eCard"},"White on black text":{"string":"White on black text"},"Announcement":{"string":"Announcement"},"The download for %@ could not be completed.":{"string":"The download for %@ could not be completed."},"The book you were trying to read is corrupted. Please try downloading it again.":{"string":"The book you were trying to read is corrupted. Please try downloading it again."},"Don't have a library card?":{"string":"Don't have a library card?"},"Loading... Please wait.":{"string":"Loading... Please wait."},"Duration":{"string":"Duration"},"Fast Forward %d seconds":{"string":"Fast Forward %d seconds"},"DRM Error":{"string":"DRM Error"},"Search Reservations":{"string":"Search Reservations"},"Move":{"string":"Move"},"Get":{"string":"Get"},"Description":{"string":"Description"},"We're sorry. Currently we do not support signups for new patrons via the app.":{"string":"We're sorry. Currently we do not support signups for new patrons via the app."},"Cancels the failed download for this book: %@":{"string":"Cancels the failed download for this book: %@"},"Some books will be unavailable in this version. Please try updating to the latest version of the application.":{"string":"Some books will be unavailable in this version. Please try updating to the latest version of the application."},"%d seconds":{"string":"%d seconds"},"Return":{"string":"Return"},"Published":{"string":"Published"},"Open Settings":{"string":"Open Settings"},"Unkown error occurred. Please try again.":{"string":"Unkown error occurred. Please try again."},"Selecting \"Delete\" will remove all bookmarks from the server for %@.":{"string":"Selecting \"Delete\" will remove all bookmarks from the server for %@."},"Your authentication details have expired. Please sign in again.":{"string":"Your authentication details have expired. Please sign in again."},"Previous Chapter":{"string":"Previous Chapter"},"GCDAsyncSocketClosedError":{"string":"Socket closed by remote peer"},"2.0×":{"string":"2.0×"},"%@ remaining in the book.":{"string":"%@ remaining in the book."},"Are you sure you want to delete \"%@\"?":{"string":"Are you sure you want to delete \"%@\"?"},"An unknown error occurred while trying to sign out.":{"string":"An unknown error occurred while trying to sign out."},"Playback Speed":{"string":"Playback Speed"},"No Results Found":{"string":"No Results Found"},"Please check your connection and try again.":{"string":"Please check your connection and try again."},"Two times normal speed. Fastest.":{"string":"Two times normal speed. Fastest."},"currently":{"string":"currently"},"Accept":{"string":"Accept"},"Retry the failed download for this book: %@":{"string":"Retry the failed download for this book: %@"},"year_suffix_short":{"string":"{???, plural, one {1 y} other {%d y}}"},"Available for checkout in less than %@.":{"string":"Available for checkout in less than %@."}}} \ No newline at end of file +{ + "en" : { + "\nYou are %ld in line for %ld copies." : { + "string" : "\nYou are %1$ld in line for %2$ld copies." + }, + "%02d hr %02 dmin" : { + "string" : "%1$d hr %2$d min" + }, + "%02d hr, %02d min remaining" : { + "string" : "%1$d hr, %2$d min remaining" + }, + "%02d min remaining" : { + "string" : "%02d min remaining" + }, + "%02d:%02d" : { + "string" : "%1$d:%2$d" + }, + "%02d:%02d:%02d" : { + "string" : "%1$d:%2$d:%3$d" + }, + "%02dmin" : { + "string" : "%02dmin" + }, + "%@" : { + "string" : "%@" + }, + "%@ %@" : { + "string" : "%1$@ %2$@" + }, + "%@ (file %@ of %d)" : { + "string" : "%1$@ (file %2$@ of %3$d)" + }, + "%@ played. %@ remaining." : { + "string" : "%1$@ played. %2$@ remaining." + }, + "%@ remaining" : { + "string" : "%@ remaining" + }, + "%@ remaining in the book." : { + "string" : "%@ remaining in the book." + }, + "%@ through chapter" : { + "string" : "%@ through chapter" + }, + "%@ until playback pauses" : { + "string" : "%@ until playback pauses" + }, + "%@ version %@ (%@)" : { + "string" : "%1$@ version %2$@ (%3$@)" + }, + "%@%" : { + "string" : "%1$@%2$" + }, + "%d hour and %d minute" : { + "string" : "%1$d hour and %2$d minute" + }, + "%d hour and %d minutes" : { + "string" : "%1$d hour and %2$d minutes" + }, + "%d hours and %d minute" : { + "string" : "%1$d hours and %2$d minute" + }, + "%d hours and %d minutes" : { + "string" : "%1$d hours and %2$d minutes" + }, + "%d hours, %d minutes and %d seconds" : { + "string" : "%1$d hours, %2$d minutes and %3$d seconds" + }, + "%d minute" : { + "string" : "%d minute" + }, + "%d minutes" : { + "string" : "%d minutes" + }, + "%d minutes and %d seconds" : { + "string" : "%1$d minutes and %2$d seconds" + }, + "%d second" : { + "string" : "%d second" + }, + "%d seconds" : { + "string" : "%d seconds" + }, + "(book.title) is an Adobe PDF, which is not supported." : { + "string" : "(book.title) is an Adobe PDF, which is not supported." + }, + "(dateType.rawValue)_suffix_long" : { + "string" : "(dateType.rawValue)_suffix_long" + }, + "(dateType.rawValue)_suffix_short" : { + "string" : "(dateType.rawValue)_suffix_short" + }, + "0.75×" : { + "string" : "0.75×" + }, + "1.0×" : { + "string" : "1.0×" + }, + "1.0× (Normal)" : { + "string" : "1.0× (Normal)" + }, + "1.25×" : { + "string" : "1.25×" + }, + "1.50×" : { + "string" : "1.50×" + }, + "13 or Older" : { + "string" : "13 or Older" + }, + "15 Minutes" : { + "string" : "15 Minutes" + }, + "2.0×" : { + "string" : "2.0×" + }, + "30 Minutes" : { + "string" : "30 Minutes" + }, + "60 Minutes" : { + "string" : "60 Minutes" + }, + "<>" : { + "string" : "<>" + }, + "A" : { + "string" : "A" + }, + "A Problem Has Occurred" : { + "string" : "A Problem Has Occurred" + }, + "A bookmark has already been saved at this location." : { + "string" : "A bookmark has already been saved at this location." + }, + "ABCabc" : { + "string" : "ABCabc" + }, + "AVAILABLE FOR CHECKOUT" : { + "string" : "AVAILABLE FOR CHECKOUT" + }, + "Aa" : { + "string" : "Aa" + }, + "About" : { + "string" : "About" + }, + "About App" : { + "string" : "About App" + }, + "Accept" : { + "string" : "Accept" + }, + "Accessibility Statement" : { + "string" : "Accessibility Statement" + }, + "AccessibilitySwitchLibrary" : { + "string" : "AccessibilitySwitchLibrary" + }, + "Account" : { + "string" : "Account" + }, + "Acknowledgements" : { + "string" : "Acknowledgements" + }, + "Add Bookmark" : { + "string" : "Add Bookmark" + }, + "Add Library" : { + "string" : "Add Library" + }, + "Advanced" : { + "string" : "Advanced" + }, + "Age Verification" : { + "string" : "Age Verification" + }, + "All licenses of this book are currently checked out." : { + "string" : "All licenses of this book are currently checked out." + }, + "An error occurred during the authentication process" : { + "string" : "An error occurred during the authentication process" + }, + "An error was encountered while parsing the server response." : { + "string" : "An error was encountered while parsing the server response." + }, + "An error was encountered while trying to open this book." : { + "string" : "An error was encountered while trying to open this book." + }, + "An unknown error occurred while trying to sign out." : { + "string" : "An unknown error occurred while trying to sign out." + }, + "An unknown error occurred. Please check your connection or try again later." : { + "string" : "An unknown error occurred. Please check your connection or try again later." + }, + "Announcement" : { + "string" : "Announcement" + }, + "Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book." + }, + "Are you sure you want to delete \"%@\"?" : { + "string" : "Are you sure you want to delete \"%@\"?" + }, + "Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book." + }, + "Are you sure you want to return \"%@\"?" : { + "string" : "Are you sure you want to return \"%@\"?" + }, + "Audiobook" : { + "string" : "Audiobook" + }, + "Authenticate to reveal your PIN." : { + "string" : "Authenticate to reveal your PIN." + }, + "Authentication Expired" : { + "string" : "Authentication Expired" + }, + "Authentication Required" : { + "string" : "Authentication Required" + }, + "Author" : { + "string" : "Author" + }, + "Available for checkout in less than %@." : { + "string" : "Available for checkout in less than %@." + }, + "Back" : { + "string" : "Back" + }, + "Barcode or Username" : { + "string" : "Barcode or Username" + }, + "Black on sepia text" : { + "string" : "Black on sepia text" + }, + "Book Cover" : { + "string" : "Book Cover" + }, + "Book format" : { + "string" : "Book format" + }, + "Book format:" : { + "string" : "Book format:" + }, + "Bookmark added" : { + "string" : "Bookmark added" + }, + "Bookmarks" : { + "string" : "Bookmarks" + }, + "Borrow Failed" : { + "string" : "Borrow Failed" + }, + "Borrowing %@ could not be completed." : { + "string" : "Borrowing %@ could not be completed." + }, + "BrightnessSlider" : { + "string" : "BrightnessSlider" + }, + "Browse Books" : { + "string" : "Browse Books" + }, + "By signing in, you agree the End User License Agreement" : { + "string" : "By signing in, you agree the End User License Agreement" + }, + "By signing in, you agree to the End User License Agreement." : { + "string" : "By signing in, you agree to the End User License Agreement." + }, + "Camera Access Disabled" : { + "string" : "Camera Access Disabled" + }, + "Cancel" : { + "string" : "Cancel" + }, + "Cancels hold for %@" : { + "string" : "Cancels hold for %@" + }, + "Cancels the download for the current book: %@" : { + "string" : "Cancels the download for the current book: %@" + }, + "Cancels the failed download for this book: %@" : { + "string" : "Cancels the failed download for this book: %@" + }, + "Categories" : { + "string" : "Categories" + }, + "Category" : { + "string" : "Category" + }, + "Chapters" : { + "string" : "Chapters" + }, + "Check Connection" : { + "string" : "Check Connection" + }, + "Check Out" : { + "string" : "Check Out" + }, + "Close" : { + "string" : "Close" + }, + "Connection Failed" : { + "string" : "Connection Failed" + }, + "Content Licenses" : { + "string" : "Content Licenses" + }, + "Contents" : { + "string" : "Contents" + }, + "Continue" : { + "string" : "Continue" + }, + "Continue without signing in" : { + "string" : "Continue without signing in" + }, + "Corrupted Audiobook" : { + "string" : "Corrupted Audiobook" + }, + "Create Card" : { + "string" : "Create Card" + }, + "Currently Playing: %@" : { + "string" : "Currently Playing: %@" + }, + "DRM Error" : { + "string" : "DRM Error" + }, + "DecreaseFontSize" : { + "string" : "DecreaseFontSize" + }, + "Default book font" : { + "string" : "Default book font" + }, + "Delete" : { + "string" : "Delete" + }, + "Delete Server Data" : { + "string" : "Delete Server Data" + }, + "Deletes %@" : { + "string" : "Deletes %@" + }, + "Description" : { + "string" : "Description" + }, + "Distributed by: " : { + "string" : "Distributed by: " + }, + "Do you want to move to the page on which you left off?" : { + "string" : "Do you want to move to the page on which you left off?" + }, + "Do you want to move to the time on which you left off?" : { + "string" : "Do you want to move to the time on which you left off?" + }, + "Don't have a library card?" : { + "string" : "Don't have a library card?" + }, + "Done" : { + "string" : "Done" + }, + "Download" : { + "string" : "Download" + }, + "Download Error" : { + "string" : "Download Error" + }, + "Downloading" : { + "string" : "Downloading" + }, + "Downloading:" : { + "string" : "Downloading:" + }, + "Downloading: %@%%" : { + "string" : "Downloading: %@%%" + }, + "Downloads %@" : { + "string" : "Downloads %@" + }, + "Duration" : { + "string" : "Duration" + }, + "E-Library Sync" : { + "string" : "E-Library Sync" + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "E-kirjasto requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "E-kirjasto requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." + }, + "E-kirjasto test login" : { + "string" : "E-kirjasto test login" + }, + "Enable Sync" : { + "string" : "Enable Sync" + }, + "Enable sync to save your reading position and bookmarks to your other devices.\n\nYou can change this any time in Settings." : { + "string" : "Enable sync to save your reading position and bookmarks to your other devices.\n\nYou can change this any time in Settings." + }, + "End of Chapter" : { + "string" : "End of Chapter" + }, + "Error" : { + "string" : "Error" + }, + "Error Changing Sync Setting" : { + "string" : "Error Changing Sync Setting" + }, + "Error Loading Library" : { + "string" : "Error Loading Library" + }, + "Error extracting encrypted PDF file" : { + "string" : "Error extracting encrypted PDF file" + }, + "FAQ" : { + "string" : "FAQ" + }, + "Failed to get current location. Please try again." : { + "string" : "Failed to get current location. Please try again." + }, + "Fast Forward %d seconds" : { + "string" : "Fast Forward %d seconds" + }, + "Feedback" : { + "string" : "Feedback" + }, + "Find Your Library" : { + "string" : "Find Your Library" + }, + "Forgot your password?" : { + "string" : "Forgot your password?" + }, + "GCDAsyncSocketClosedError" : { + "string" : "Socket closed by remote peer" + }, + "GCDAsyncSocketConnectTimeoutError" : { + "string" : "Attempt to connect to host timed out" + }, + "GCDAsyncSocketReadMaxedOutError" : { + "string" : "Read operation reached set maximum length" + }, + "GCDAsyncSocketReadTimeoutError" : { + "string" : "Read operation timed out" + }, + "GCDAsyncSocketWriteTimeoutError" : { + "string" : "Write operation timed out" + }, + "Get" : { + "string" : "Get" + }, + "Gets %@" : { + "string" : "Gets %@" + }, + "Hide Barcode" : { + "string" : "Hide Barcode" + }, + "Holds %@" : { + "string" : "Holds %@" + }, + "ISBN" : { + "string" : "ISBN" + }, + "If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing." : { + "string" : "If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing." + }, + "If you are under 13, all content downloaded to My Books will be removed." : { + "string" : "If you are under 13, all content downloaded to My Books will be removed." + }, + "If you sign out without enabling Sync, your books and any saved bookmarks will be removed." : { + "string" : "If you sign out without enabling Sync, your books and any saved bookmarks will be removed." + }, + "If you sign out, your books and any saved bookmarks will be removed." : { + "string" : "If you sign out, your books and any saved bookmarks will be removed." + }, + "Illustrators" : { + "string" : "Illustrators" + }, + "IncreaseFontSize" : { + "string" : "IncreaseFontSize" + }, + "Information" : { + "string" : "Information" + }, + "Internal Error, bookmark failed to save." : { + "string" : "Internal Error, bookmark failed to save." + }, + "Invalid Credentials" : { + "string" : "Invalid Credentials" + }, + "It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?" : { + "string" : "It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?" + }, + "It will expire in %@." : { + "string" : "It will expire in %@." + }, + "Keep" : { + "string" : "Keep" + }, + "Kirjaudu palveluun" : { + "string" : "Kirjaudu palveluun" + }, + "Language" : { + "string" : "Language" + }, + "Less than 1 min remaining" : { + "string" : "Less than 1 min remaining" + }, + "Libraries" : { + "string" : "Libraries" + }, + "Listen" : { + "string" : "Listen" + }, + "Load error. Please try signing out, then log in again." : { + "string" : "Load error. Please try signing out, then log in again." + }, + "Loading... Please wait." : { + "string" : "Loading... Please wait." + }, + "Location Recovery Error" : { + "string" : "Location Recovery Error" + }, + "Login" : { + "string" : "Login" + }, + "Login Failed" : { + "string" : "Login Failed" + }, + "Magazines" : { + "string" : "Magazines" + }, + "More" : { + "string" : "More" + }, + "More %@ books" : { + "string" : "More %@ books" + }, + "More..." : { + "string" : "More..." + }, + "Move" : { + "string" : "Move" + }, + "My Books" : { + "string" : "My Books" + }, + "Narrators" : { + "string" : "Narrators" + }, + "Next" : { + "string" : "Next" + }, + "Next Chapter" : { + "string" : "Next Chapter" + }, + "No Results Found" : { + "string" : "No Results Found" + }, + "No email account is set for this device." : { + "string" : "No email account is set for this device." + }, + "Normal speed." : { + "string" : "Normal speed." + }, + "Not Now" : { + "string" : "Not Now" + }, + "OK" : { + "string" : "OK" + }, + "Off" : { + "string" : "Off" + }, + "One and a half times faster than normal speed." : { + "string" : "One and a half times faster than normal speed." + }, + "One and one quarter faster than normal speed." : { + "string" : "One and one quarter faster than normal speed." + }, + "Open Settings" : { + "string" : "Open Settings" + }, + "Open dyslexic font" : { + "string" : "Open dyslexic font" + }, + "Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works." : { + "string" : "Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works." + }, + "Opens %@ for reading" : { + "string" : "Opens %@ for reading" + }, + "Opens audiobook %@ for listening" : { + "string" : "Opens audiobook %@ for listening" + }, + "PDF" : { + "string" : "PDF" + }, + "PIN" : { + "string" : "PIN" + }, + "PIN code:" : { + "string" : "PIN code:" + }, + "Page %d of " : { + "string" : "Page %d of " + }, + "Pause" : { + "string" : "Pause" + }, + "Play" : { + "string" : "Play" + }, + "Play Sample" : { + "string" : "Play Sample" + }, + "Playback Destination" : { + "string" : "Playback Destination" + }, + "Playback Speed" : { + "string" : "Playback Speed" + }, + "Please check your connection and try again." : { + "string" : "Please check your connection and try again." + }, + "Please check your username and password and try again." : { + "string" : "Please check your username and password and try again." + }, + "Please contact %@ to report an issue." : { + "string" : "Please contact %@ to report an issue." + }, + "Please enter your birth year" : { + "string" : "Please enter your birth year" + }, + "Please try again later." : { + "string" : "Please try again later." + }, + "Please wait" : { + "string" : "Please wait" + }, + "Please wait a moment before switching library accounts" : { + "string" : "Please wait a moment before switching library accounts" + }, + "Please wait..." : { + "string" : "Please wait..." + }, + "Previous Chapter" : { + "string" : "Previous Chapter" + }, + "Privacy Policy" : { + "string" : "Privacy Policy" + }, + "Prompt login" : { + "string" : "Prompt login" + }, + "Published" : { + "string" : "Published" + }, + "Publisher" : { + "string" : "Publisher" + }, + "Puuttuvatko tunnukset?" : { + "string" : "Puuttuvatko tunnukset?" + }, + "Reached the end of the results." : { + "string" : "Reached the end of the results." + }, + "Read" : { + "string" : "Read" + }, + "Read more" : { + "string" : "Read more" + }, + "Reader settings" : { + "string" : "Reader settings" + }, + "Ready for Download" : { + "string" : "Ready for Download" + }, + "Register a passkey" : { + "string" : "Register a passkey" + }, + "Reject" : { + "string" : "Reject" + }, + "Rekisteröidy palveluun" : { + "string" : "Rekisteröidy palveluun" + }, + "Reload" : { + "string" : "Reload" + }, + "Remove" : { + "string" : "Remove" + }, + "Remove Bookmark" : { + "string" : "Remove Bookmark" + }, + "Remove Reservation" : { + "string" : "Remove Reservation" + }, + "Report an Issue" : { + "string" : "Report an Issue" + }, + "Request New Codes" : { + "string" : "Request New Codes" + }, + "Requesting" : { + "string" : "Requesting" + }, + "Reservations" : { + "string" : "Reservations" + }, + "Reserve" : { + "string" : "Reserve" + }, + "Resume" : { + "string" : "Resume" + }, + "Retry" : { + "string" : "Retry" + }, + "Retry the failed download for this book: %@" : { + "string" : "Retry the failed download for this book: %@" + }, + "Return" : { + "string" : "Return" + }, + "Returns %@" : { + "string" : "Returns %@" + }, + "Rewind %d seconds" : { + "string" : "Rewind %d seconds" + }, + "Salasana unohtunut?" : { + "string" : "Salasana unohtunut?" + }, + "Salasano unohtunut?" : { + "string" : "Salasano unohtunut?" + }, + "Sample" : { + "string" : "Sample" + }, + "Sans font" : { + "string" : "Sans font" + }, + "Save the current location bookmark for later listening." : { + "string" : "Save the current location bookmark for later listening." + }, + "Save your reading position and bookmarks to all your other devices." : { + "string" : "Save your reading position and bookmarks to all your other devices." + }, + "Search" : { + "string" : "Search" + }, + "Search My Books" : { + "string" : "Search My Books" + }, + "Search Reservations" : { + "string" : "Search Reservations" + }, + "Select Year" : { + "string" : "Select Year" + }, + "Select a chapter or track from a list." : { + "string" : "Select a chapter or track from a list." + }, + "Selecting \"Delete\" will remove all bookmarks from the server for %@." : { + "string" : "Selecting \"Delete\" will remove all bookmarks from the server for %@." + }, + "Serif font" : { + "string" : "Serif font" + }, + "Settings" : { + "string" : "Settings" + }, + "Show" : { + "string" : "Show" + }, + "Show Barcode" : { + "string" : "Show Barcode" + }, + "Sign In Error" : { + "string" : "Sign In Error" + }, + "Sign in" : { + "string" : "Sign in" + }, + "Sign in with a passkey" : { + "string" : "Sign in with a passkey" + }, + "Sign in with suomi.fi" : { + "string" : "Sign in with suomi.fi" + }, + "Sign out" : { + "string" : "Sign out" + }, + "Signing out" : { + "string" : "Signing out" + }, + "Sleep Timer" : { + "string" : "Sleep Timer" + }, + "Software Licenses" : { + "string" : "Software Licenses" + }, + "Some books will be unavailable in this version. Please try updating to the latest version of the application." : { + "string" : "Some books will be unavailable in this version. Please try updating to the latest version of the application." + }, + "Something went wrong with the Adobe DRM system" : { + "string" : "Something went wrong with the Adobe DRM system" + }, + "Sort By:" : { + "string" : "Sort By:" + }, + "Stay" : { + "string" : "Stay" + }, + "Submit" : { + "string" : "Submit" + }, + "Sync Bookmarks" : { + "string" : "Sync Bookmarks" + }, + "Sync Listening Position" : { + "string" : "Sync Listening Position" + }, + "Sync Reading Position" : { + "string" : "Sync Reading Position" + }, + "Table of Contents" : { + "string" : "Table of Contents" + }, + "Table of contents" : { + "string" : "Table of contents" + }, + "Table of contents and bookmarks" : { + "string" : "Table of contents and bookmarks" + }, + "Testing" : { + "string" : "Testing" + }, + "Thank You" : { + "string" : "Thank You" + }, + "The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu." : { + "string" : "The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu." + }, + "The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." + }, + "The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." + }, + "The audiobook you are trying to open appears to be corrupted. Try downloading it again." : { + "string" : "The audiobook you are trying to open appears to be corrupted. Try downloading it again." + }, + "The book license has expired." : { + "string" : "The book license has expired." + }, + "The book you were trying to open is invalid." : { + "string" : "The book you were trying to open is invalid." + }, + "The book you were trying to read is corrupted. Please try downloading it again." : { + "string" : "The book you were trying to read is corrupted. Please try downloading it again." + }, + "The book you were trying to read is in an unsupported format." : { + "string" : "The book you were trying to read is in an unsupported format." + }, + "The download could not be completed." : { + "string" : "The download could not be completed." + }, + "The download could not be completed.\nScroll down to 'View Issues' to see details." : { + "string" : "The download could not be completed.\nScroll down to 'View Issues' to see details." + }, + "The download for %@ could not be completed." : { + "string" : "The download for %@ could not be completed." + }, + "The item you are trying to open is not currently supported." : { + "string" : "The item you are trying to open is not currently supported." + }, + "The page could not load due to a conection error." : { + "string" : "The page could not load due to a conection error." + }, + "The page could not load due to a connection error." : { + "string" : "The page could not load due to a connection error." + }, + "The return of %@ could not be completed." : { + "string" : "The return of %@ could not be completed." + }, + "The title you reserved, (book.title), is available." : { + "string" : "The title you reserved, (book.title), is available." + }, + "There are no bookmarks for this book." : { + "string" : "There are no bookmarks for this book." + }, + "There are no results" : { + "string" : "There are no results" + }, + "There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later." : { + "string" : "There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later." + }, + "This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk." : { + "string" : "This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk." + }, + "This book is available to borrow." : { + "string" : "This book is available to borrow." + }, + "This reservation will be automatically cancelled in %@." : { + "string" : "This reservation will be automatically cancelled in %@." + }, + "Three quarters of normal speed. Slower." : { + "string" : "Three quarters of normal speed. Slower." + }, + "Title" : { + "string" : "Title" + }, + "Track %@" : { + "string" : "Track %@" + }, + "Translators" : { + "string" : "Translators" + }, + "Try Again" : { + "string" : "Try Again" + }, + "Try force-quitting the app and repeat the sign-in process." : { + "string" : "Try force-quitting the app and repeat the sign-in process." + }, + "Two times normal speed. Fastest." : { + "string" : "Two times normal speed. Fastest." + }, + "Unable to contact the server because the URL for signing in is missing." : { + "string" : "Unable to contact the server because the URL for signing in is missing." + }, + "Unable to load PDF file" : { + "string" : "Unable to load PDF file" + }, + "Unable to load the web page at this time." : { + "string" : "Unable to load the web page at this time." + }, + "Under 13" : { + "string" : "Under 13" + }, + "Unkown error occurred. Please try again." : { + "string" : "Unkown error occurred. Please try again." + }, + "Unsupported Item" : { + "string" : "Unsupported Item" + }, + "Unsupported format" : { + "string" : "Unsupported format" + }, + "User Agreement" : { + "string" : "User Agreement" + }, + "User denied location access. Go to system settings to enable location access for E-kirjasto." : { + "string" : "User denied location access. Go to system settings to enable location access for E-kirjasto." + }, + "User denied location access. Go to system settings to enable location access for the Palace App." : { + "string" : "User denied location access. Go to system settings to enable location access for the Palace App." + }, + "Username:" : { + "string" : "Username:" + }, + "Verifying" : { + "string" : "Verifying" + }, + "View Sample" : { + "string" : "View Sample" + }, + "View sample for %@" : { + "string" : "View sample for %@" + }, + "Visit the Catalog to\nadd books to My Books." : { + "string" : "Visit the Catalog to\nadd books to My Books." + }, + "WAITING FOR AVAILABILITY" : { + "string" : "WAITING FOR AVAILABILITY" + }, + "Wait" : { + "string" : "Wait" + }, + "We can’t get your library right now. Please close and reopen the app to try again." : { + "string" : "We can’t get your library right now. Please close and reopen the app to try again." + }, + "We're sorry. Currently we do not support signups for new patrons via the app." : { + "string" : "We're sorry. Currently we do not support signups for new patrons via the app." + }, + "We're sorry. Our sign up system is currently down. Please try again later." : { + "string" : "We're sorry. Our sign up system is currently down. Please try again later." + }, + "Welcome to Open eBooks" : { + "string" : "Welcome to Open eBooks" + }, + "When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download." : { + "string" : "When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download." + }, + "White on black text" : { + "string" : "White on black text" + }, + "Would you like to return it?" : { + "string" : "Would you like to return it?" + }, + "You are %ld in line for %ld copies." : { + "string" : "You are %1$ld in line for %2$ld copies." + }, + "You are %ld in line." : { + "string" : "You are %ld in line." + }, + "You have already checked out this loan. You may need to refresh your My Books list to download the title." : { + "string" : "You have already checked out this loan. You may need to refresh your My Books list to download the title." + }, + "You have disabled location services for this app." : { + "string" : "You have disabled location services for this app." + }, + "You must enable camera access for this application in order to sign up for a library card." : { + "string" : "You must enable camera access for this application in order to sign up for a library card." + }, + "You need to login to access the collection." : { + "string" : "You need to login to access the collection." + }, + "Your Audiobook Has Finished" : { + "string" : "Your Audiobook Has Finished" + }, + "Your authentication details have expired. Please sign in again." : { + "string" : "Your authentication details have expired. Please sign in again." + }, + "Your book has not yet been downloaded." : { + "string" : "Your book has not yet been downloaded." + }, + "Your book is ready to read!" : { + "string" : "Your book is ready to read!" + }, + "Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?" : { + "string" : "Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?" + }, + "Your report will be reviewed as soon as possible." : { + "string" : "Your report will be reviewed as soon as possible." + }, + "accessibilityShowAndReloadCatalogTab" : { + "string" : "accessibilityShowAndReloadCatalogTab" + }, + "currently" : { + "string" : "currently" + }, + "day_suffix_long" : { + "string" : "{???, plural, one {1 day} other {%d days}}" + }, + "day_suffix_short" : { + "string" : "{???, plural, one {1 d} other {%d d}}" + }, + "eCard" : { + "string" : "eCard" + }, + "ePub" : { + "string" : "ePub" + }, + "hour_suffix_long" : { + "string" : "{???, plural, one {1 hour} other {%d hours}}" + }, + "hour_suffix_short" : { + "string" : "{???, plural, one {1 h} other {%d h}}" + }, + "month_suffix_long" : { + "string" : "{???, plural, one {1 month} other {%d months}}" + }, + "month_suffix_short" : { + "string" : "{???, plural, one {1 m} other {%d m}}" + }, + "sec" : { + "string" : "sec" + }, + "week_suffix_long" : { + "string" : "{???, plural, one {1 week} other {%d weeks}}" + }, + "week_suffix_short" : { + "string" : "{???, plural, one {1 w} other {%d w}}" + }, + "year_suffix_long" : { + "string" : "{???, plural, one {1 year} other {%d years}}" + }, + "year_suffix_short" : { + "string" : "{???, plural, one {1 y} other {%d y}}" + } + }, + "fi" : { + "\nYou are %ld in line for %ld copies." : { + "string" : "\nOlet sijalla %1$ld jonossa %2$ld teoksen osalta." + }, + "%02d hr %02 dmin" : { + "string" : "%1$d h %2$d min" + }, + "%02d hr, %02d min remaining" : { + "string" : "%1$d h, %2$d min jäljellä" + }, + "%02d min remaining" : { + "string" : "%02d min jäljellä" + }, + "%02d:%02d" : { + "string" : "%1$d:%2$d" + }, + "%02d:%02d:%02d" : { + "string" : "%1$d:%2$d:%3$d" + }, + "%02dmin" : { + "string" : "%02dmin" + }, + "%@" : { + "string" : "%@" + }, + "%@ %@" : { + "string" : "%1$@ %2$@" + }, + "%@ (file %@ of %d)" : { + "string" : "%1$@ (tiedosto %2$@/%3$d)" + }, + "%@ played. %@ remaining." : { + "string" : "%1$@ toistettu. %2$@ jäljellä." + }, + "%@ remaining" : { + "string" : "%@ jäljellä" + }, + "%@ remaining in the book." : { + "string" : "%@ jäljellä kirjassa." + }, + "%@ through chapter" : { + "string" : "%@ luvusta" + }, + "%@ until playback pauses" : { + "string" : "%@ kunnes toisto keskeytyy" + }, + "%@ version %@ (%@)" : { + "string" : "%1$@ versio %2$@ (%3$@)" + }, + "%@%" : { + "string" : "%1$@%2$" + }, + "%d hour and %d minute" : { + "string" : "%1$d tunti ja %2$d minuutti" + }, + "%d hour and %d minutes" : { + "string" : "%1$d tunti ja %2$d minuuttia" + }, + "%d hours and %d minute" : { + "string" : "%1$d tuntia ja %2$d minuutti" + }, + "%d hours and %d minutes" : { + "string" : "%1$d tuntia ja %2$d minuuttia" + }, + "%d hours, %d minutes and %d seconds" : { + "string" : "%1$d tuntia, %2$d minuuttia ja %3$d sekuntia" + }, + "%d minute" : { + "string" : "%d minuutti" + }, + "%d minutes" : { + "string" : "%d minuuttia" + }, + "%d minutes and %d seconds" : { + "string" : "%1$d minuuttia ja %2$d sekuntia" + }, + "%d second" : { + "string" : "%d sekunti" + }, + "%d seconds" : { + "string" : "%d sekuntia" + }, + "(book.title) is an Adobe PDF, which is not supported." : { + "string" : "(book.title) on Adobe PDF -tiedosto, jota ei tueta." + }, + "(dateType.rawValue)_suffix_long" : { + "string" : "(dateType.rawValue)_suffix_long" + }, + "(dateType.rawValue)_suffix_short" : { + "string" : "(dateType.rawValue)_suffix_short" + }, + "0.75×" : { + "string" : "0.75×" + }, + "1.0×" : { + "string" : "1.0×" + }, + "1.0× (Normal)" : { + "string" : "1.0× (normaali)" + }, + "1.25×" : { + "string" : "1.25×" + }, + "1.50×" : { + "string" : "1.50×" + }, + "13 or Older" : { + "string" : "13 tai vanhempi" + }, + "15 Minutes" : { + "string" : "15 minuuttia" + }, + "2.0×" : { + "string" : "2.0×" + }, + "30 Minutes" : { + "string" : "30 minuuttia" + }, + "60 Minutes" : { + "string" : "60 minuuttia" + }, + "<>" : { + "string" : "<>" + }, + "A" : { + "string" : "A" + }, + "A Problem Has Occurred" : { + "string" : "Ilmeni ongelma" + }, + "A bookmark has already been saved at this location." : { + "string" : "Tähän kohtaan on jo tallennettu kirjanmerkki." + }, + "ABCabc" : { + "string" : "ABCabc" + }, + "AVAILABLE FOR CHECKOUT" : { + "string" : "LAINATTAVISSA" + }, + "Aa" : { + "string" : "Aa" + }, + "About" : { + "string" : "Tietoja" + }, + "About App" : { + "string" : "Tietoja sovelluksesta" + }, + "Accept" : { + "string" : "Hyväksy" + }, + "Accessibility Statement" : { + "string" : "Saavutettavuusseloste" + }, + "AccessibilitySwitchLibrary" : { + "string" : "AccessibilitySwitchLibrary" + }, + "Account" : { + "string" : "Tili" + }, + "Acknowledgements" : { + "string" : "Kiitokset" + }, + "Add Bookmark" : { + "string" : "Lisää kirjanmerkki" + }, + "Add Library" : { + "string" : "Lisää kirjasto" + }, + "Advanced" : { + "string" : "Edistynyt" + }, + "Age Verification" : { + "string" : "Iän vahvistus" + }, + "All licenses of this book are currently checked out." : { + "string" : "Kaikki tämän kirjan lisenssit on tällä hetkellä lainattu." + }, + "An error occurred during the authentication process" : { + "string" : "Todennusprosessin aikana tapahtui virhe" + }, + "An error was encountered while parsing the server response." : { + "string" : "Palvelimen vastauksen jäsennyksessä havaittiin virhe." + }, + "An error was encountered while trying to open this book." : { + "string" : "Kirjaa avattaessa tapahtui virhe." + }, + "An unknown error occurred while trying to sign out." : { + "string" : "Tuntematon virhe tapahtui, kun yritit kirjautua ulos." + }, + "An unknown error occurred. Please check your connection or try again later." : { + "string" : "Tapahtui tuntematon virhe. Tarkista internetyhteys tai yritä myöhemmin uudelleen." + }, + "Announcement" : { + "string" : "Ilmoitus" + }, + "Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Haluatko varmasti poistaa teoksen %@ varauksistasi? Sen jälkeen et enää jonota tätä kirjaa." + }, + "Are you sure you want to delete \"%@\"?" : { + "string" : "Haluatko varmasti poistaa teoksen %@?" + }, + "Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Haluatko varmasti poistaa teoksen %@ varauksistasi? Sen jälkeen et enää jonota tätä kirjaa." + }, + "Are you sure you want to return \"%@\"?" : { + "string" : "Haluatko varmasti palauttaa teoksen %@?" + }, + "Audiobook" : { + "string" : "Äänikirja" + }, + "Authenticate to reveal your PIN." : { + "string" : "Tunnistaudu PIN-koodisi selvittämiseksi." + }, + "Authentication Expired" : { + "string" : "Todennus vanhentunut" + }, + "Authentication Required" : { + "string" : "Todennus vaaditaan" + }, + "Author" : { + "string" : "Tekijä" + }, + "Available for checkout in less than %@." : { + "string" : "Saatavilla lainattavaksi alle %@ kuluttua." + }, + "Back" : { + "string" : "Takaisin" + }, + "Barcode or Username" : { + "string" : "Viivakoodi tai käyttäjänimi" + }, + "Black on sepia text" : { + "string" : "Musta teksti seepialla" + }, + "Book Cover" : { + "string" : "Kirjan kansi" + }, + "Book format" : { + "string" : "" + }, + "Book format:" : { + "string" : "Kirjan tiedostomuoto:" + }, + "Bookmark added" : { + "string" : "Kirjanmerkki lisättiin" + }, + "Bookmarks" : { + "string" : "Kirjanmerkit" + }, + "Borrow Failed" : { + "string" : "Lainaus epäonnistui" + }, + "Borrowing %@ could not be completed." : { + "string" : "Teoksen %@ lainausta ei voitu suorittaa loppuun." + }, + "BrightnessSlider" : { + "string" : "BrightnessSlider" + }, + "Browse Books" : { + "string" : "Selaa kirjoja" + }, + "By signing in, you agree the End User License Agreement" : { + "string" : "Kirjautumalla sisään hyväksyt loppukäyttäjän lisenssisopimuksen" + }, + "By signing in, you agree to the End User License Agreement." : { + "string" : "Kirjautumalla sisään hyväksyt loppukäyttäjän lisenssisopimuksen." + }, + "Camera Access Disabled" : { + "string" : "Kameran käyttöoikeus estetty" + }, + "Cancel" : { + "string" : "Peruuta" + }, + "Cancels hold for %@" : { + "string" : "Peruuttaa kohteen %@ varauksen" + }, + "Cancels the download for the current book: %@" : { + "string" : "Peruuttaa nykyisen kirjan latauksen: %@" + }, + "Cancels the failed download for this book: %@" : { + "string" : "Peruuttaa tämän kirjan epäonnistuneen latauksen: %@" + }, + "Categories" : { + "string" : "Luokat" + }, + "Category" : { + "string" : "Luokka" + }, + "Chapters" : { + "string" : "Luvut" + }, + "Check Connection" : { + "string" : "Tarkista yhteys" + }, + "Check Out" : { + "string" : "Lainaa" + }, + "Close" : { + "string" : "Sulje" + }, + "Connection Failed" : { + "string" : "Yhteyden muodostaminen epäonnistui" + }, + "Content Licenses" : { + "string" : "Sisältölisenssit" + }, + "Contents" : { + "string" : "Sisältö" + }, + "Continue" : { + "string" : "Jatka" + }, + "Continue without signing in" : { + "string" : "Jatka kirjautumatta sisään" + }, + "Corrupted Audiobook" : { + "string" : "Vioittunut äänikirja" + }, + "Create Card" : { + "string" : "Luo kortti" + }, + "Currently Playing: %@" : { + "string" : "Toistetaan parhaillaan: %@" + }, + "DRM Error" : { + "string" : "DRM-virhe" + }, + "DecreaseFontSize" : { + "string" : "DecreaseFontSize" + }, + "Default book font" : { + "string" : "Kirjan oletusfontti" + }, + "Delete" : { + "string" : "Poista" + }, + "Delete Server Data" : { + "string" : "Poista palvelimen tiedot" + }, + "Deletes %@" : { + "string" : "Poistaa kohteen %@" + }, + "Description" : { + "string" : "Kuvaus" + }, + "Distributed by: " : { + "string" : "Jakelija:" + }, + "Do you want to move to the page on which you left off?" : { + "string" : "Haluatko siirtyä sivulle, jolle jäit?" + }, + "Do you want to move to the time on which you left off?" : { + "string" : "Haluatko siirtyä kohtaan, johon jäit?" + }, + "Don't have a library card?" : { + "string" : "Eikö sinulla ole kirjastokorttia?" + }, + "Done" : { + "string" : "Valmis" + }, + "Download" : { + "string" : "Lataa" + }, + "Download Error" : { + "string" : "Latausvirhe" + }, + "Downloading" : { + "string" : "Ladataan" + }, + "Downloading:" : { + "string" : "Ladataan:" + }, + "Downloading: %@%%" : { + "string" : "Ladataan: %@%%" + }, + "Downloads %@" : { + "string" : "Lataa kohdetta %@" + }, + "Duration" : { + "string" : "Kesto" + }, + "E-Library Sync" : { + "string" : "" + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "E-kirjasto vaatii kertaluonteisen sijainnin tarkistuksen, jotta kirjastopalvelualueesi voidaan vahvistaa. Valitse ensin Luo kortti ja valitse sitten ponnahdusikkunassa Salli kerran, jotta voimme vahvistaa tämän tiedon." + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "E-kirjasto vaatii kertaluonteisen sijainnin tarkistuksen, jotta kirjastopalvelualueesi voidaan vahvistaa. Olet poistanut sijaintipalvelut käytöstä tämän sovelluksen kohdalla. Ota ne käyttöön valitsemalla alla oleva Avaa asetukset -painike. Jatka sen jälkeen kortin luomista." + }, + "E-kirjasto test login" : { + "string" : "" + }, + "Enable Sync" : { + "string" : "" + }, + "Enable sync to save your reading position and bookmarks to your other devices.\n\nYou can change this any time in Settings." : { + "string" : "" + }, + "End of Chapter" : { + "string" : "Luvun loppu" + }, + "Error" : { + "string" : "Virhe" + }, + "Error Changing Sync Setting" : { + "string" : "Virhe synkronointiasetuksen muuttamisessa" + }, + "Error Loading Library" : { + "string" : "Virhe kirjaston lataamisessa" + }, + "Error extracting encrypted PDF file" : { + "string" : "Virhe salatun PDF-tiedoston purkamisessa" + }, + "FAQ" : { + "string" : "" + }, + "Failed to get current location. Please try again." : { + "string" : "Tämänhetkisen sijainnin hakeminen epäonnistui. Yritä uudelleen." + }, + "Fast Forward %d seconds" : { + "string" : "Kelaa eteenpäin %d sekuntia" + }, + "Feedback" : { + "string" : "Palaute" + }, + "Find Your Library" : { + "string" : "Etsi kirjastosi" + }, + "Forgot your password?" : { + "string" : "Unohditko salasanasi?" + }, + "GCDAsyncSocketClosedError" : { + "string" : "Etäkumppani sulki yhteyden" + }, + "GCDAsyncSocketConnectTimeoutError" : { + "string" : "Yritys muodostaa yhteys isäntäkoneeseen aikakatkaistiin" + }, + "GCDAsyncSocketReadMaxedOutError" : { + "string" : "Lukutoiminto saavutti asetetun enimmäispituuden" + }, + "GCDAsyncSocketReadTimeoutError" : { + "string" : "Lukutoiminto aikakatkaistiin" + }, + "GCDAsyncSocketWriteTimeoutError" : { + "string" : "Kirjoitustoiminto aikakatkaistiin" + }, + "Get" : { + "string" : "Lainaa" + }, + "Gets %@" : { + "string" : "Hakee kohteen %@" + }, + "Hide Barcode" : { + "string" : "Piilota viivakoodi" + }, + "Holds %@" : { + "string" : "Varaa kohteen %@" + }, + "ISBN" : { + "string" : "" + }, + "If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing." : { + "string" : "Jos toinen laite on käytettävissä, lähetä ääni Bluetoothin tai Airplayn kautta. Muussa tapauksessa älä tee mitään." + }, + "If you are under 13, all content downloaded to My Books will be removed." : { + "string" : "Jos olet alle 13-vuotias, kaikki Omat kirjat -kohtaan ladattu sisältö poistetaan." + }, + "If you sign out without enabling Sync, your books and any saved bookmarks will be removed." : { + "string" : "Jos kirjaudut ulos ottamatta synkronointia käyttöön, kirjasi ja tallennetut kirjanmerkkisi poistetaan." + }, + "If you sign out, your books and any saved bookmarks will be removed." : { + "string" : "Jos kirjaudut ulos, kirjasi ja tallennetut kirjanmerkkisi poistetaan." + }, + "Illustrators" : { + "string" : "" + }, + "IncreaseFontSize" : { + "string" : "IncreaseFontSize" + }, + "Information" : { + "string" : "Tiedot" + }, + "Internal Error, bookmark failed to save." : { + "string" : "Sisäinen virhe, kirjanmerkin tallennus epäonnistui." + }, + "Invalid Credentials" : { + "string" : "Virheelliset kirjautumistiedot" + }, + "It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?" : { + "string" : "Näyttää siltä, että sinulla saattaa olla kirjan lataus tai palautus käynnissä. Haluatko keskeyttää sen ja jatkaa uloskirjautumista?" + }, + "It will expire in %@." : { + "string" : "Se vanhenee seuraavan ajan kuluttua: %@." + }, + "Keep" : { + "string" : "Säilytä" + }, + "Kirjaudu palveluun" : { + "string" : "Kirjaudu palveluun" + }, + "Language" : { + "string" : "" + }, + "Less than 1 min remaining" : { + "string" : "Alle 1 min jäljellä" + }, + "Libraries" : { + "string" : "Kirjastot" + }, + "Listen" : { + "string" : "Kuuntele" + }, + "Load error. Please try signing out, then log in again." : { + "string" : "Latausvirhe. Kokeile kirjautua ulos ja sitten uudelleen sisään." + }, + "Loading... Please wait." : { + "string" : "Ladataan... Odota." + }, + "Location Recovery Error" : { + "string" : "Sijainnin palautusvirhe" + }, + "Login" : { + "string" : "" + }, + "Login Failed" : { + "string" : "Sisäänkirjautuminen epäonnistui" + }, + "Magazines" : { + "string" : "Aikakauslehdet" + }, + "More" : { + "string" : "Lisää" + }, + "More %@ books" : { + "string" : "Lisää kirjoja: %@" + }, + "More..." : { + "string" : "Lisää..." + }, + "Move" : { + "string" : "Siirry" + }, + "My Books" : { + "string" : "Omat lainat" + }, + "Narrators" : { + "string" : "Lukijat" + }, + "Next" : { + "string" : "Seuraava" + }, + "Next Chapter" : { + "string" : "Seuraava luku" + }, + "No Results Found" : { + "string" : "Ei hakutuloksia" + }, + "No email account is set for this device." : { + "string" : "Tälle laitteelle ei ole määritetty sähköpostitiliä." + }, + "Normal speed." : { + "string" : "Normaali nopeus." + }, + "Not Now" : { + "string" : "" + }, + "OK" : { + "string" : "OK" + }, + "Off" : { + "string" : "Pois" + }, + "One and a half times faster than normal speed." : { + "string" : "Puolitoista kertaa normaalia nopeutta nopeammin." + }, + "One and one quarter faster than normal speed." : { + "string" : "Yksi ja yksi neljäsosa normaalia nopeutta nopeammin." + }, + "Open Settings" : { + "string" : "Avaa asetukset" + }, + "Open dyslexic font" : { + "string" : "Open dyslexic -fontti" + }, + "Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works." : { + "string" : "Open eBooks tarjoaa ilmaisia kirjoja niitä eniten tarvitseville lapsille.\n\nKokoelmaan kuuluu tuhansia suosittuja ja palkittuja julkaisuja sekä satoja tekijänoikeuksista vapaita teoksia." + }, + "Opens %@ for reading" : { + "string" : "Avaa teoksen %@ lukemista varten" + }, + "Opens audiobook %@ for listening" : { + "string" : "Avaa äänikirjan %@ kuuntelua varten" + }, + "PDF" : { + "string" : "PDF" + }, + "PIN" : { + "string" : "PIN" + }, + "PIN code:" : { + "string" : "" + }, + "Page %d of " : { + "string" : "Sivu %d/ " + }, + "Pause" : { + "string" : "Keskeytä" + }, + "Play" : { + "string" : "Toista" + }, + "Play Sample" : { + "string" : "Toista näyte" + }, + "Playback Destination" : { + "string" : "Toiston kohde" + }, + "Playback Speed" : { + "string" : "Toistonopeus" + }, + "Please check your connection and try again." : { + "string" : "Tarkista internetyhteys ja yritä uudelleen." + }, + "Please check your username and password and try again." : { + "string" : "Tarkista käyttäjänimesi ja salasanasi, ja yritä uudelleen." + }, + "Please contact %@ to report an issue." : { + "string" : "Ilmoita ongelmasta ottamalla yhteyttä kohteeseen %@." + }, + "Please enter your birth year" : { + "string" : "Anna syntymävuotesi" + }, + "Please try again later." : { + "string" : "Yritä myöhemmin uudelleen." + }, + "Please wait" : { + "string" : "Odota" + }, + "Please wait a moment before switching library accounts" : { + "string" : "Odota hetki ennen kuin vaihdat kirjastotiliä" + }, + "Please wait..." : { + "string" : "Odota..." + }, + "Previous Chapter" : { + "string" : "Edellinen luku" + }, + "Privacy Policy" : { + "string" : "Tietosuojakäytäntö" + }, + "Prompt login" : { + "string" : "Sisäänkirjautuminen kehotteella" + }, + "Published" : { + "string" : "Julkaistu" + }, + "Publisher" : { + "string" : "Kustantaja" + }, + "Puuttuvatko tunnukset?" : { + "string" : "Puuttuvatko tunnukset?" + }, + "Reached the end of the results." : { + "string" : "Päästiin tulosten loppuun." + }, + "Read" : { + "string" : "Lue" + }, + "Read more" : { + "string" : "Lue lisää" + }, + "Reader settings" : { + "string" : "Lukijan asetukset" + }, + "Ready for Download" : { + "string" : "Valmis ladattavaksi" + }, + "Register a passkey" : { + "string" : "Rekisteröi pääsyavain" + }, + "Reject" : { + "string" : "Hylkää" + }, + "Rekisteröidy palveluun" : { + "string" : "Rekisteröidy palveluun" + }, + "Reload" : { + "string" : "Lataa uudelleen" + }, + "Remove" : { + "string" : "Poista" + }, + "Remove Bookmark" : { + "string" : "Poista kirjanmerkki" + }, + "Remove Reservation" : { + "string" : "Poista varaus" + }, + "Report an Issue" : { + "string" : "Ilmoita ongelmasta" + }, + "Request New Codes" : { + "string" : "Pyydä uusia koodeja" + }, + "Requesting" : { + "string" : "Pyydetään" + }, + "Reservations" : { + "string" : "Varaukset" + }, + "Reserve" : { + "string" : "Varaa" + }, + "Resume" : { + "string" : "Jatka" + }, + "Retry" : { + "string" : "Yritä uudelleen" + }, + "Retry the failed download for this book: %@" : { + "string" : "Yritä ladata tämä kirja uudelleen: %@" + }, + "Return" : { + "string" : "Palauta" + }, + "Returns %@" : { + "string" : "Palauttaa kohteen %@" + }, + "Rewind %d seconds" : { + "string" : "Kelaa taaksepäin %d sekuntia" + }, + "Salasana unohtunut?" : { + "string" : "Unohditko salasanasi?" + }, + "Salasano unohtunut?" : { + "string" : "Salasana unohtunut?" + }, + "Sample" : { + "string" : "Näyte" + }, + "Sans font" : { + "string" : "Sans-fontti" + }, + "Save the current location bookmark for later listening." : { + "string" : "Tallenna tämänhetkinen sijainti kirjanmerkiksi myöhempää kuuntelua varten." + }, + "Save your reading position and bookmarks to all your other devices." : { + "string" : "Tallenna lukukohtasi ja kirjanmerkkisi kaikkiin muihin laitteisiisi." + }, + "Search" : { + "string" : "Haku" + }, + "Search My Books" : { + "string" : "Hae Omat lainat -listasta." + }, + "Search Reservations" : { + "string" : "Hae varauksista" + }, + "Select Year" : { + "string" : "Valitse vuosi" + }, + "Select a chapter or track from a list." : { + "string" : "Valitse luku tai kappale listalta." + }, + "Selecting \"Delete\" will remove all bookmarks from the server for %@." : { + "string" : "Jos valitset Poista, kaikki teoksen %@ kirjanmerkit poistetaan palvelimelta." + }, + "Serif font" : { + "string" : "Serif-fontti" + }, + "Settings" : { + "string" : "Asetukset" + }, + "Show" : { + "string" : "Näytä" + }, + "Show Barcode" : { + "string" : "Näytä viivakoodi" + }, + "Sign In Error" : { + "string" : "Kirjautumisvirhe" + }, + "Sign in" : { + "string" : "Kirjaudu sisään" + }, + "Sign in with a passkey" : { + "string" : "Kirjaudu sisään pääsyavaimella" + }, + "Sign in with suomi.fi" : { + "string" : "Kirjaudu sisään suomi.fi-tunnistuksella" + }, + "Sign out" : { + "string" : "Kirjaudu ulos" + }, + "Signing out" : { + "string" : "Kirjaudutaan ulos" + }, + "Sleep Timer" : { + "string" : "Uniajastin" + }, + "Software Licenses" : { + "string" : "Ohjelmistolisenssit" + }, + "Some books will be unavailable in this version. Please try updating to the latest version of the application." : { + "string" : "Jotkut kirjat eivät ole saatavilla tässä versiossa. Kokeile päivittää sovellus uusimpaan versioon." + }, + "Something went wrong with the Adobe DRM system" : { + "string" : "Jokin meni pieleen Adoben DRM-järjestelmässä" + }, + "Sort By:" : { + "string" : "Lajitteluperuste:" + }, + "Stay" : { + "string" : "Pysy" + }, + "Submit" : { + "string" : "Lähetä" + }, + "Sync Bookmarks" : { + "string" : "Synkronoi kirjanmerkit" + }, + "Sync Listening Position" : { + "string" : "Synkronoi kuuntelukohta" + }, + "Sync Reading Position" : { + "string" : "Synkronoi lukukohta" + }, + "Table of Contents" : { + "string" : "Sisällysluettelo" + }, + "Table of contents" : { + "string" : "Sisällysluettelo" + }, + "Table of contents and bookmarks" : { + "string" : "Sisällysluettelo ja kirjanmerkit" + }, + "Testing" : { + "string" : "Testaus" + }, + "Thank You" : { + "string" : "Kiitos" + }, + "The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu." : { + "string" : "DRM-kirjastolla kestää odotettua kauemmin. Odota ja yritä myöhemmin uudelleen.\n\nJos ongelma jatkuu, kokeile kirjautua ulos ja uudelleen sisään Kirjaston asetukset -valikosta." + }, + "The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "Palace-sovellus vaatii kertaluonteisen sijainnin tarkistuksen, jotta kirjastopalvelualueesi voidaan vahvistaa. Valitse ensin Luo kortti ja valitse sitten ponnahdusikkunassa Salli kerran, jotta voimme vahvistaa tämän tiedon." + }, + "The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "Palace-sovellus vaatii kertaluonteisen sijainnin tarkistuksen, jotta kirjastopalvelualueesi voidaan vahvistaa. Olet poistanut sijaintipalvelut käytöstä tämän sovelluksen kohdalla. Ota ne käyttöön valitsemalla alla oleva Avaa asetukset -painike. Jatka sen jälkeen kortin luomista." + }, + "The audiobook you are trying to open appears to be corrupted. Try downloading it again." : { + "string" : "Äänikirja, jota yrität avata, vaikuttaa olevan vioittunut. Kokeile ladata se uudelleen." + }, + "The book license has expired." : { + "string" : "Kirjan lisenssi on vanhentunut." + }, + "The book you were trying to open is invalid." : { + "string" : "Kirja, jonka yritit avata, on virheellinen." + }, + "The book you were trying to read is corrupted. Please try downloading it again." : { + "string" : "Kirja, jota yritit lukea, on vioittunut. Yritä ladata se uudelleen." + }, + "The book you were trying to read is in an unsupported format." : { + "string" : "Yritit lukea kirjaa, jonka muotoa ei tueta." + }, + "The download could not be completed." : { + "string" : "Latausta ei voitu suorittaa loppuun." + }, + "The download could not be completed.\nScroll down to 'View Issues' to see details." : { + "string" : "Latausta ei voitu suorittaa loppuun.\nKatso tiedot selaamalla alaspäin kohtaan Näytä ongelmat." + }, + "The download for %@ could not be completed." : { + "string" : "Teoksen %@ latausta ei voitu suorittaa loppuun." + }, + "The item you are trying to open is not currently supported." : { + "string" : "Kohdetta, jota yrität avata, ei tueta tällä hetkellä." + }, + "The page could not load due to a conection error." : { + "string" : "Sivua ei voitu ladata yhteysvirheen vuoksi." + }, + "The page could not load due to a connection error." : { + "string" : "Sivua ei voitu ladata yhteysvirheen vuoksi." + }, + "The return of %@ could not be completed." : { + "string" : "Teoksen %@ palautusta ei voitu suorittaa loppuun." + }, + "The title you reserved, (book.title), is available." : { + "string" : "Varaamasi teos (book.title) on saatavilla." + }, + "There are no bookmarks for this book." : { + "string" : "Tässä kirjassa ei ole kirjanmerkkejä." + }, + "There are no results" : { + "string" : "Ei hakutuloksia" + }, + "There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later." : { + "string" : "Yhteyden muodostamisessa palvelimeen oli ongelma.\nVarmista, että internetyhteytesi toimii, tai yritä myöhemmin uudelleen." + }, + "This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk." : { + "string" : "Tätä URL-osoitetta ei löydy. Sulje sovellus kokonaan ja lataa se uudelleen. Jos ongelma jatkuu, ota yhteyttä kirjastosi tukipalveluun." + }, + "This book is available to borrow." : { + "string" : "Tämän kirjan voi lainata." + }, + "This reservation will be automatically cancelled in %@." : { + "string" : "Tämä varaus peruutetaan automaattisesti seuraavan ajan kuluttua: %@." + }, + "Three quarters of normal speed. Slower." : { + "string" : "Kolme neljäsosaa normaalista nopeudesta. Hitaampi." + }, + "Title" : { + "string" : "Nimi" + }, + "Track %@" : { + "string" : "Kappale %@" + }, + "Translators" : { + "string" : "" + }, + "Try Again" : { + "string" : "Yritä uudelleen" + }, + "Try force-quitting the app and repeat the sign-in process." : { + "string" : "Kokeile pakottaa sovelluksen sulkeminen ja toista sisäänkirjautumisprosessi." + }, + "Two times normal speed. Fastest." : { + "string" : "Kaksi kertaa normaali nopeus. Nopein." + }, + "Unable to contact the server because the URL for signing in is missing." : { + "string" : "Palvelimeen ei saada yhteyttä, koska sisäänkirjautumisen URL-osoite puuttuu." + }, + "Unable to load PDF file" : { + "string" : "PDF-tiedostoa ei voitu ladata" + }, + "Unable to load the web page at this time." : { + "string" : "Verkkosivua ei voida ladata tällä hetkellä." + }, + "Under 13" : { + "string" : "Alle 13" + }, + "Unkown error occurred. Please try again." : { + "string" : "Tapahtui tuntematon virhe. Yritä uudelleen." + }, + "Unsupported Item" : { + "string" : "Kohdetta ei tueta" + }, + "Unsupported format" : { + "string" : "Muotoa ei tueta" + }, + "User Agreement" : { + "string" : "Käyttäjäsopimus" + }, + "User denied location access. Go to system settings to enable location access for E-kirjasto." : { + "string" : "Käyttäjä kielsi sijaintitietojen käytön. Siirry järjestelmän asetuksiin ja ota sijaintitiedot käyttöön E-kirjastossa." + }, + "User denied location access. Go to system settings to enable location access for the Palace App." : { + "string" : "Käyttäjä kielsi sijaintitietojen käytön. Siirry järjestelmän asetuksiin ja ota sijaintitiedot käyttöön Palace-sovelluksessa." + }, + "Username:" : { + "string" : "" + }, + "Verifying" : { + "string" : "Vahvistetaan" + }, + "View Sample" : { + "string" : "Katso näyte" + }, + "View sample for %@" : { + "string" : "Katso näyte kohteesta %@" + }, + "Visit the Catalog to\nadd books to My Books." : { + "string" : "Sinulla ei ole voimassa olevia lainoja." + }, + "WAITING FOR AVAILABILITY" : { + "string" : "ODOTETAAN SAATAVUUTTA" + }, + "Wait" : { + "string" : "Odota" + }, + "We can’t get your library right now. Please close and reopen the app to try again." : { + "string" : "Emme pääse kirjastoosi tällä hetkellä. Yritä uudelleen sulkemalla sovellus ja avaamalla se uudelleen." + }, + "We're sorry. Currently we do not support signups for new patrons via the app." : { + "string" : "Emme valitettavasti tällä hetkellä tue uusien asiakkaiden rekisteröitymistä sovelluksen kautta." + }, + "We're sorry. Our sign up system is currently down. Please try again later." : { + "string" : "Olemme pahoillamme. Kirjautumisjärjestelmämme on tällä hetkellä poissa käytöstä. Yritä myöhemmin uudelleen." + }, + "Welcome to Open eBooks" : { + "string" : "Tervetuloa Open eBooksiin" + }, + "When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download." : { + "string" : "Sinulla ei ole voimassa olevia varauksia." + }, + "White on black text" : { + "string" : "Valkoinen teksti mustalla" + }, + "Would you like to return it?" : { + "string" : "Haluatko palauttaa sen?" + }, + "You are %ld in line for %ld copies." : { + "string" : "Olet sijalla %1$ld jonossa %2$ld teoksen osalta." + }, + "You are %ld in line." : { + "string" : "Olet jonossa sijalla %ld." + }, + "You have already checked out this loan. You may need to refresh your My Books list to download the title." : { + "string" : "Olet jo lainannut tämän teoksen. Sinun on ehkä päivitettävä Omat lainat -listasi, jotta voit ladata teoksen." + }, + "You have disabled location services for this app." : { + "string" : "Olet poistanut tämän sovelluksen sijaintipalvelut käytöstä." + }, + "You must enable camera access for this application in order to sign up for a library card." : { + "string" : "Sinun on sallittava kameran käyttö tässä sovelluksessa, jotta voit rekisteröityä kirjastokortin käyttäjäksi." + }, + "You need to login to access the collection." : { + "string" : "Sinun on kirjauduttava sisään, jotta voit käyttää kokoelmaa." + }, + "Your Audiobook Has Finished" : { + "string" : "Äänikirjasi on päättynyt" + }, + "Your authentication details have expired. Please sign in again." : { + "string" : "Tunnistautumistietosi ovat vanhentuneet. Kirjaudu uudelleen sisään." + }, + "Your book has not yet been downloaded." : { + "string" : "Kirjaasi ei ole vielä ladattu." + }, + "Your book is ready to read!" : { + "string" : "Kirjasi on valmis luettavaksi!" + }, + "Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?" : { + "string" : "Kirjanmerkkejäsi ja lukukohtiasi tallennetaan parhaillaan palvelimelle. Haluatko keskeyttää sen ja jatkaa uloskirjautumista?" + }, + "Your report will be reviewed as soon as possible." : { + "string" : "Ilmoituksesi tarkistetaan mahdollisimman pian." + }, + "accessibilityShowAndReloadCatalogTab" : { + "string" : "accessibilityShowAndReloadCatalogTab" + }, + "currently" : { + "string" : "tällä hetkellä" + }, + "day_suffix_long" : { + "string" : "{???, plural, one {1 päivä} other {%d päivää}}" + }, + "day_suffix_short" : { + "string" : "{???, plural, one {1 pv} other {%d pv}}" + }, + "eCard" : { + "string" : "eCard" + }, + "ePub" : { + "string" : "ePub" + }, + "hour_suffix_long" : { + "string" : "{???, plural, one {1 tunti} other {%d tuntia}}" + }, + "hour_suffix_short" : { + "string" : "{???, plural, one {1 h} other {%d h}}" + }, + "month_suffix_long" : { + "string" : "{???, plural, one {1 kuukausi} other {%d kuukautta}}" + }, + "month_suffix_short" : { + "string" : "{???, plural, one {1 kk} other {%d kk}}" + }, + "sec" : { + "string" : "s" + }, + "week_suffix_long" : { + "string" : "{???, plural, one {1 viikko} other {%d viikkoa}}" + }, + "week_suffix_short" : { + "string" : "{???, plural, one {1 vk} other {%d vk}}" + }, + "year_suffix_long" : { + "string" : "{???, plural, one {1 vuosi} other {%d vuotta}}" + }, + "year_suffix_short" : { + "string" : "{???, plural, one {1 v} other {%d v}}" + } + }, + "sv" : { + "\nYou are %ld in line for %ld copies." : { + "string" : "\nDu är på plats %1$ld i kö för %2$ld kopior." + }, + "%02d hr %02 dmin" : { + "string" : "%1$d h %2$d min" + }, + "%02d hr, %02d min remaining" : { + "string" : "%1$d h, %2$d min återstår" + }, + "%02d min remaining" : { + "string" : "%02d min återstår" + }, + "%02d:%02d" : { + "string" : "%1$d:%2$d" + }, + "%02d:%02d:%02d" : { + "string" : "%1$d:%2$d:%3$d" + }, + "%02dmin" : { + "string" : "%02dmin" + }, + "%@" : { + "string" : "%@" + }, + "%@ %@" : { + "string" : "%1$@ %2$@" + }, + "%@ (file %@ of %d)" : { + "string" : "%1$@ (fil %2$@ av %3$d)" + }, + "%@ played. %@ remaining." : { + "string" : "%1$@ uppspelat. %2$@ återstår." + }, + "%@ remaining" : { + "string" : "%@ återstår" + }, + "%@ remaining in the book." : { + "string" : "%@ återstår av boken." + }, + "%@ through chapter" : { + "string" : "%@ igenom kapitlet" + }, + "%@ until playback pauses" : { + "string" : "%@ tills uppspelningen pausas" + }, + "%@ version %@ (%@)" : { + "string" : "%1$@ version %2$@ (%3$@)" + }, + "%@%" : { + "string" : "%1$@%2$" + }, + "%d hour and %d minute" : { + "string" : "%1$d timme och %2$d minut" + }, + "%d hour and %d minutes" : { + "string" : "%1$d timmar och %2$d minuter" + }, + "%d hours and %d minute" : { + "string" : "%1$d timmar och %2$d minut" + }, + "%d hours and %d minutes" : { + "string" : "%1$d timmar och %2$d minuter" + }, + "%d hours, %d minutes and %d seconds" : { + "string" : "%1$d timmar, %2$d minuter och %3$d sekunder" + }, + "%d minute" : { + "string" : "%d minut" + }, + "%d minutes" : { + "string" : "%d minuter" + }, + "%d minutes and %d seconds" : { + "string" : "%1$d minuter och %2$d sekunder" + }, + "%d second" : { + "string" : "%d sekund" + }, + "%d seconds" : { + "string" : "%d sekunder" + }, + "(book.title) is an Adobe PDF, which is not supported." : { + "string" : "(book.title) är en Adobe PDF och stöds således inte." + }, + "(dateType.rawValue)_suffix_long" : { + "string" : "(dateType.rawValue)_suffix_long" + }, + "(dateType.rawValue)_suffix_short" : { + "string" : "(dateType.rawValue)_suffix_short" + }, + "0.75×" : { + "string" : "0.75×" + }, + "1.0×" : { + "string" : "1.0×" + }, + "1.0× (Normal)" : { + "string" : "1,0× (Normal)" + }, + "1.25×" : { + "string" : "1.25×" + }, + "1.50×" : { + "string" : "1.50×" + }, + "13 or Older" : { + "string" : "13 eller äldre" + }, + "15 Minutes" : { + "string" : "15 minuter" + }, + "2.0×" : { + "string" : "2,0×" + }, + "30 Minutes" : { + "string" : "30 minuter" + }, + "60 Minutes" : { + "string" : "60 minuter" + }, + "<>" : { + "string" : "<>" + }, + "A" : { + "string" : "A" + }, + "A Problem Has Occurred" : { + "string" : "Det har inträffat ett problem" + }, + "A bookmark has already been saved at this location." : { + "string" : "Ett bokmärke har redan sparats på denna position." + }, + "ABCabc" : { + "string" : "ABCabc" + }, + "AVAILABLE FOR CHECKOUT" : { + "string" : "KAN LÅNAS" + }, + "Aa" : { + "string" : "Aa" + }, + "About" : { + "string" : "Om" + }, + "About App" : { + "string" : "Om appen" + }, + "Accept" : { + "string" : "Godkänn" + }, + "Accessibility Statement" : { + "string" : "Tillgänglighetsutlåtande" + }, + "AccessibilitySwitchLibrary" : { + "string" : "AccessibilitySwitchLibrary" + }, + "Account" : { + "string" : "Konto" + }, + "Acknowledgements" : { + "string" : "Tillkännagivanden" + }, + "Add Bookmark" : { + "string" : "Lägg till bokmärke" + }, + "Add Library" : { + "string" : "Lägg till bibliotek" + }, + "Advanced" : { + "string" : "Avancerat" + }, + "Age Verification" : { + "string" : "Ålderskontroll" + }, + "All licenses of this book are currently checked out." : { + "string" : "Alla licenser för denna bok är i användning." + }, + "An error occurred during the authentication process" : { + "string" : "Ett fel uppstod under autentiseringsprocessen" + }, + "An error was encountered while parsing the server response." : { + "string" : "Ett fel uppstod vid parsning av serversvaret." + }, + "An error was encountered while trying to open this book." : { + "string" : "Det uppstod ett fel med att öppna boken." + }, + "An unknown error occurred while trying to sign out." : { + "string" : "Ett okänt fel uppstod vid utloggning." + }, + "An unknown error occurred. Please check your connection or try again later." : { + "string" : "Det har uppstått ett okänt fel. Kontrollera din anslutning eller försök på nytt senare." + }, + "Announcement" : { + "string" : "Tillkännagivande" + }, + "Are you sure you want ot remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Är du säker att du vill ta bort \"%@\" från dina reservationer? Du kommer inte längre att stå i kö till denna bok." + }, + "Are you sure you want to delete \"%@\"?" : { + "string" : "Är du säker att du vill radera \"%@\"?" + }, + "Are you sure you want to remove \"%@\" from your reservations? You will no longer be in line for this book." : { + "string" : "Är du säker att du vill ta bort \"%@\" från dina reservationer? Du kommer inte längre att stå i kö till denna bok." + }, + "Are you sure you want to return \"%@\"?" : { + "string" : "Är du säker att du vill lämna tillbaka \"%@\"?" + }, + "Audiobook" : { + "string" : "Ljudbok" + }, + "Authenticate to reveal your PIN." : { + "string" : "Autentisera för att visa din PIN." + }, + "Authentication Expired" : { + "string" : "Autentiseringen har förfallit" + }, + "Authentication Required" : { + "string" : "Autentisering krävs" + }, + "Author" : { + "string" : "Författare" + }, + "Available for checkout in less than %@." : { + "string" : "Kan lånas om mindre än %@." + }, + "Back" : { + "string" : "Tillbaka" + }, + "Barcode or Username" : { + "string" : "Streckkod eller användarnamn" + }, + "Black on sepia text" : { + "string" : "Svart text mot sepiabakgrund" + }, + "Book Cover" : { + "string" : "Bokomslag" + }, + "Book format" : { + "string" : "" + }, + "Book format:" : { + "string" : "Bokformat:" + }, + "Bookmark added" : { + "string" : "Bokmärke lades till" + }, + "Bookmarks" : { + "string" : "Bokmärken" + }, + "Borrow Failed" : { + "string" : "Det gick inte att låna" + }, + "Borrowing %@ could not be completed." : { + "string" : "Det gick inte att låna %@." + }, + "BrightnessSlider" : { + "string" : "Reglage för ljusstryka" + }, + "Browse Books" : { + "string" : "Bläddra bland böcker" + }, + "By signing in, you agree the End User License Agreement" : { + "string" : "Genom att logga in godkänner du slutanvändaravtalet" + }, + "By signing in, you agree to the End User License Agreement." : { + "string" : "Genom att logga in godkänner du slutanvändaravtalet." + }, + "Camera Access Disabled" : { + "string" : "Kameraåtkomst inaktiverad" + }, + "Cancel" : { + "string" : "Ångra" + }, + "Cancels hold for %@" : { + "string" : "Avbryter reservationen för %@" + }, + "Cancels the download for the current book: %@" : { + "string" : "Avbryter nedladdningen av den valda boken: %@" + }, + "Cancels the failed download for this book: %@" : { + "string" : "Avbryter den misslyckade nedladdningen av denna bok: %@" + }, + "Categories" : { + "string" : "Kategorier" + }, + "Category" : { + "string" : "Kategori" + }, + "Chapters" : { + "string" : "Kapitel" + }, + "Check Connection" : { + "string" : "Kontrollera anslutningen" + }, + "Check Out" : { + "string" : "Låna" + }, + "Close" : { + "string" : "Stäng" + }, + "Connection Failed" : { + "string" : "Anslutning misslyckades" + }, + "Content Licenses" : { + "string" : "Innehållslicenser" + }, + "Contents" : { + "string" : "Innehåll" + }, + "Continue" : { + "string" : "Fortsätt" + }, + "Continue without signing in" : { + "string" : "Fortsätt utan att logga in" + }, + "Corrupted Audiobook" : { + "string" : "Skadad ljudbok" + }, + "Create Card" : { + "string" : "Skapa kort" + }, + "Currently Playing: %@" : { + "string" : "Spelar upp: %@" + }, + "DRM Error" : { + "string" : "DRM-fel" + }, + "DecreaseFontSize" : { + "string" : "Minska teckenstorlek" + }, + "Default book font" : { + "string" : "Standard typsnitt" + }, + "Delete" : { + "string" : "Radera" + }, + "Delete Server Data" : { + "string" : "Radera serverdata" + }, + "Deletes %@" : { + "string" : "Raderar %@" + }, + "Description" : { + "string" : "Beskrivning" + }, + "Distributed by: " : { + "string" : "Distribuerad av:" + }, + "Do you want to move to the page on which you left off?" : { + "string" : "Vill du gå till den sida där du slutade?" + }, + "Do you want to move to the time on which you left off?" : { + "string" : "Vill du gå till den punkt där du slutade?" + }, + "Don't have a library card?" : { + "string" : "Har du inget bibliotekskort?" + }, + "Done" : { + "string" : "Klar" + }, + "Download" : { + "string" : "Ladda ner" + }, + "Download Error" : { + "string" : "Fel vid nedladdning" + }, + "Downloading" : { + "string" : "Laddar ner" + }, + "Downloading:" : { + "string" : "Laddar ner:" + }, + "Downloading: %@%%" : { + "string" : "Laddar ner: %@%%" + }, + "Downloads %@" : { + "string" : "Nedladdningar %@" + }, + "Duration" : { + "string" : "Längd" + }, + "E-Library Sync" : { + "string" : "" + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "E-biblioteket behöver kontrollera din position en gång för att verifiera ditt område för bibliotekstjänster. Efter att du valt \"Skapa kort\" välj \"Tillåt en gång\" i popup-fönstret så att vi kan verifiera denna information." + }, + "E-kirjasto requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "E-biblioteket behöver kontrollera din position en gång för att verifiera ditt område för bibliotekstjänster. Du har inaktiverat positionstjänsten för denna app. För att aktivera den peka på knappen Öppna inställningar nedan för att fortsätta skapa kort." + }, + "E-kirjasto test login" : { + "string" : "" + }, + "Enable Sync" : { + "string" : "" + }, + "Enable sync to save your reading position and bookmarks to your other devices.\n\nYou can change this any time in Settings." : { + "string" : "" + }, + "End of Chapter" : { + "string" : "Kapitel slut" + }, + "Error" : { + "string" : "Fel" + }, + "Error Changing Sync Setting" : { + "string" : "Fel vid ändring av synkroniseringsinställningar" + }, + "Error Loading Library" : { + "string" : "Fel när biblioteket skulle laddas" + }, + "Error extracting encrypted PDF file" : { + "string" : "Fel vid extrahering av krypterad PDF-fil" + }, + "FAQ" : { + "string" : "" + }, + "Failed to get current location. Please try again." : { + "string" : "Det gick inte att hämta nuvarande position. Försök på nytt." + }, + "Fast Forward %d seconds" : { + "string" : "Spola framåt %d sekunder" + }, + "Feedback" : { + "string" : "Respons" + }, + "Find Your Library" : { + "string" : "Hitta ditt bibliotek" + }, + "Forgot your password?" : { + "string" : "Glömt ditt lösenord?" + }, + "GCDAsyncSocketClosedError" : { + "string" : "Socket stängd genom fjärransluten peer" + }, + "GCDAsyncSocketConnectTimeoutError" : { + "string" : "Försök att ansluta till värd överskred tidsgränsen" + }, + "GCDAsyncSocketReadMaxedOutError" : { + "string" : "Läsoperationen har nått den maximala längden" + }, + "GCDAsyncSocketReadTimeoutError" : { + "string" : "Tidsgränsen för läsoperationen överskreds" + }, + "GCDAsyncSocketWriteTimeoutError" : { + "string" : "Tidsgränsen för skrivoperationen överskreds" + }, + "Get" : { + "string" : "Hämta" + }, + "Gets %@" : { + "string" : "Hämtar %@" + }, + "Hide Barcode" : { + "string" : "Dölj streckkod" + }, + "Holds %@" : { + "string" : "Reservationer %@" + }, + "ISBN" : { + "string" : "" + }, + "If another device is available, send the audio over Bluetooth or Airplay. Otherwise do nothing." : { + "string" : "Om det finns en annan enhet tillgänglig, sänd ljudfilen med Bluetooth eller Airplay. I övriga fall behöver du inte göra något." + }, + "If you are under 13, all content downloaded to My Books will be removed." : { + "string" : "Om du är under 13 år kommer allt innehåll som laddats ner i Mina böcker att raderas." + }, + "If you sign out without enabling Sync, your books and any saved bookmarks will be removed." : { + "string" : "Om du loggar ut att synkronisera kommer dina böcker och sparade bokmärken att raderas." + }, + "If you sign out, your books and any saved bookmarks will be removed." : { + "string" : "Om du loggar ut kommer dina böcker och sparade bokmärken att raderas." + }, + "Illustrators" : { + "string" : "" + }, + "IncreaseFontSize" : { + "string" : "Öka teckenstorlek" + }, + "Information" : { + "string" : "Information" + }, + "Internal Error, bookmark failed to save." : { + "string" : "Internt fel, det gick inte att spara bokmärket." + }, + "Invalid Credentials" : { + "string" : "Ogiltiga identifieringsuppgifter" + }, + "It looks like you may have a book download or return in progress. Would you like to stop that and continue logging out?" : { + "string" : "Det verkar som om du håller på att ladda ner eller lämna tillbaka en bok. Vill du stoppa denna process och fortsätta logga ut? " + }, + "It will expire in %@." : { + "string" : "Den kommer att förfalla om %@." + }, + "Keep" : { + "string" : "Behåll" + }, + "Kirjaudu palveluun" : { + "string" : "Logga in i tjänsten" + }, + "Language" : { + "string" : "" + }, + "Less than 1 min remaining" : { + "string" : "Mindre än 1 min återstår" + }, + "Libraries" : { + "string" : "Bibliotek" + }, + "Listen" : { + "string" : "Lyssna" + }, + "Load error. Please try signing out, then log in again." : { + "string" : "Laddningsfel. Försök logga ut och sedan in igen." + }, + "Loading... Please wait." : { + "string" : "Laddar ner... Vänligen vänta." + }, + "Location Recovery Error" : { + "string" : "Fel vid återställning av position" + }, + "Login" : { + "string" : "" + }, + "Login Failed" : { + "string" : "Inloggning misslyckades" + }, + "Magazines" : { + "string" : "Tidningar" + }, + "More" : { + "string" : "Mera" + }, + "More %@ books" : { + "string" : "Flera %@ böcker" + }, + "More..." : { + "string" : "Mera..." + }, + "Move" : { + "string" : "Flytta" + }, + "My Books" : { + "string" : "Mina böcker" + }, + "Narrators" : { + "string" : "Uppläsare" + }, + "Next" : { + "string" : "Nästa" + }, + "Next Chapter" : { + "string" : "Nästa kapitel" + }, + "No Results Found" : { + "string" : "Inga resultat hittades" + }, + "No email account is set for this device." : { + "string" : "Inget e-postkonto har angetts för denna enhet." + }, + "Normal speed." : { + "string" : "Normal hastighet." + }, + "Not Now" : { + "string" : "" + }, + "OK" : { + "string" : "Ok" + }, + "Off" : { + "string" : "Av" + }, + "One and a half times faster than normal speed." : { + "string" : "En och en halv gånger snabbare än normal hastighet." + }, + "One and one quarter faster than normal speed." : { + "string" : "En och en fjärdedel snabbare än normal hastighet" + }, + "Open Settings" : { + "string" : "Öppna inställningar" + }, + "Open dyslexic font" : { + "string" : "OpenDyslexic-typsnitt" + }, + "Open eBooks provides free books to the children who need them the most.\n\nThe collection includes thousands of popular and award-winning titles as well as hundreds of public domain works." : { + "string" : "Open eBooks tillhandahåller gratis böcker för barn som behöver det mest.\n\nSamlingen omfattar tusentals populära och prisbelönta titlar samt hundratals offentliga verk." + }, + "Opens %@ for reading" : { + "string" : "Öppnar %@ för läsning" + }, + "Opens audiobook %@ for listening" : { + "string" : "Öppnar ljudboken %@ för att lyssna" + }, + "PDF" : { + "string" : "PDF" + }, + "PIN" : { + "string" : "PIN" + }, + "PIN code:" : { + "string" : "" + }, + "Page %d of " : { + "string" : "Sida %d av" + }, + "Pause" : { + "string" : "Pausa" + }, + "Play" : { + "string" : "Spela upp" + }, + "Play Sample" : { + "string" : "Spela upp utdrag" + }, + "Playback Destination" : { + "string" : "Destination för uppspelning" + }, + "Playback Speed" : { + "string" : "Uppspelningshastighet" + }, + "Please check your connection and try again." : { + "string" : "Kontrollera din anslutning och försök på nytt." + }, + "Please check your username and password and try again." : { + "string" : "Kontrollera ditt användarnamn och ditt lösenord och försök på nytt." + }, + "Please contact %@ to report an issue." : { + "string" : "Kontakta %@ för att rapportera ett problem." + }, + "Please enter your birth year" : { + "string" : "Ange ditt födelseår" + }, + "Please try again later." : { + "string" : "Försök på nytt senare." + }, + "Please wait" : { + "string" : "Vänligen vänta" + }, + "Please wait a moment before switching library accounts" : { + "string" : "Vänligen vänta en stund innan du växlar bibliotekskonto" + }, + "Please wait..." : { + "string" : "Vänligen vänta..." + }, + "Previous Chapter" : { + "string" : "Föregående kapitel" + }, + "Privacy Policy" : { + "string" : "Integritetspolicy" + }, + "Prompt login" : { + "string" : "Prompt login" + }, + "Published" : { + "string" : "Utgiven" + }, + "Publisher" : { + "string" : "Utgivare" + }, + "Puuttuvatko tunnukset?" : { + "string" : "Glömt lösenordet?" + }, + "Reached the end of the results." : { + "string" : "Du har nått slutet av resultaten." + }, + "Read" : { + "string" : "Läs" + }, + "Read more" : { + "string" : "Läs mer" + }, + "Reader settings" : { + "string" : "Läsarinställningar" + }, + "Ready for Download" : { + "string" : "Redo att laddas ner" + }, + "Register a passkey" : { + "string" : "Registrera en nyckel" + }, + "Reject" : { + "string" : "Avvisa" + }, + "Rekisteröidy palveluun" : { + "string" : "Registrera dig i tjänsten" + }, + "Reload" : { + "string" : "Ladda på nytt" + }, + "Remove" : { + "string" : "Ta bort" + }, + "Remove Bookmark" : { + "string" : "Ta bort bokmärke" + }, + "Remove Reservation" : { + "string" : "Ta bort reservation" + }, + "Report an Issue" : { + "string" : "Rapportera ett problem" + }, + "Request New Codes" : { + "string" : "Begär nya koder" + }, + "Requesting" : { + "string" : "Begär" + }, + "Reservations" : { + "string" : "Reservationer" + }, + "Reserve" : { + "string" : "Reservera" + }, + "Resume" : { + "string" : "Fortsätt" + }, + "Retry" : { + "string" : "Försök på nytt" + }, + "Retry the failed download for this book: %@" : { + "string" : "Försök ladda ner denna bok på nytt: %@" + }, + "Return" : { + "string" : "Lämna tillbaka" + }, + "Returns %@" : { + "string" : "Lämnar tillbaka %@" + }, + "Rewind %d seconds" : { + "string" : "Spola tillbaka %d sekunder" + }, + "Salasana unohtunut?" : { + "string" : "Glömt lösenordet?" + }, + "Salasano unohtunut?" : { + "string" : "Har du glömt ditt lösenord?" + }, + "Sample" : { + "string" : "Utdrag" + }, + "Sans font" : { + "string" : "Sans-typsnitt" + }, + "Save the current location bookmark for later listening." : { + "string" : "Lägg till bokmärke för nuvarande position för att lyssna senare." + }, + "Save your reading position and bookmarks to all your other devices." : { + "string" : "Spara din läsposition och bokmärken till alla dina andra enheter." + }, + "Search" : { + "string" : "Sök" + }, + "Search My Books" : { + "string" : "Sök i Mina böcker" + }, + "Search Reservations" : { + "string" : "Sök i reservationer" + }, + "Select Year" : { + "string" : "Välj år" + }, + "Select a chapter or track from a list." : { + "string" : "Välj ett kapitel eller spår från en lista." + }, + "Selecting \"Delete\" will remove all bookmarks from the server for %@." : { + "string" : "Genom att välja \"Radera\" raderas alla bokmärken för %@ från servern." + }, + "Serif font" : { + "string" : "Serif-typsnitt" + }, + "Settings" : { + "string" : "Inställningar" + }, + "Show" : { + "string" : "Visa" + }, + "Show Barcode" : { + "string" : "Visa streckkod" + }, + "Sign In Error" : { + "string" : "Inloggningsfel" + }, + "Sign in" : { + "string" : "Logga in" + }, + "Sign in with a passkey" : { + "string" : "Logga in med en nyckel" + }, + "Sign in with suomi.fi" : { + "string" : "Logga in med Suomi.fi" + }, + "Sign out" : { + "string" : "Logga ut" + }, + "Signing out" : { + "string" : "Loggar ut" + }, + "Sleep Timer" : { + "string" : "Timer för viloläge" + }, + "Software Licenses" : { + "string" : "Mjukvarulicenser" + }, + "Some books will be unavailable in this version. Please try updating to the latest version of the application." : { + "string" : "Vissa böcker kommer att vara otillgängliga i denna version. Försök uppdatera till den senaste versionen av appen." + }, + "Something went wrong with the Adobe DRM system" : { + "string" : "Något gick fel med Adobe DRM-systemet" + }, + "Sort By:" : { + "string" : "Sortera efter:" + }, + "Stay" : { + "string" : "Stanna" + }, + "Submit" : { + "string" : "Skicka" + }, + "Sync Bookmarks" : { + "string" : "Synkronisera bokmärken" + }, + "Sync Listening Position" : { + "string" : "Synkronisera läspositionen" + }, + "Sync Reading Position" : { + "string" : "Synkronisera läspositionen" + }, + "Table of Contents" : { + "string" : "Innehållsförteckning" + }, + "Table of contents" : { + "string" : "Innehållsförteckning" + }, + "Table of contents and bookmarks" : { + "string" : "Innehållsförteckning och bokmärken" + }, + "Testing" : { + "string" : "Testar" + }, + "Thank You" : { + "string" : "Tack" + }, + "The DRM Library is taking longer than expected. Please wait and try again later.\n\nIf the problem persists, try to sign out and back in again from the Library Settings menu." : { + "string" : "DRM-biblioteket tar längre tid än väntat. Vänligen vänta och försök på nytt senare.\n\nOm problemet fortsätter försök logga ut och tillbaka in via menyn för bibliteksinställningar." + }, + "The Palace App requires a one-time location check in order to verify your library service area. Once you choose \"Create Card\", please select \"Allow Once\" in the popup so we can verify this information." : { + "string" : "Palace-appen behöver kontrollera din position en gång för att verifiera ditt område för bibliotekstjänster. Efter att du valt \"Skapa kort\" välj \"Tillåt en gång\" i popup-fönstret så att vi kan verifiera denna information." + }, + "The Palace App requires a one-time location check in order to verify your library service area. You have disabled location services for this app. To enable, please select the 'Open Settings' button below then continue with card creation." : { + "string" : "Palace-appen behöver kontrollera din position en gång för att verifiera ditt område för bibliotekstjänster. Du har inaktiverat positionstjänsten för denna app. För att aktivera den peka på knappen Öppna inställningar nedan för att fortsätta skapa kort." + }, + "The audiobook you are trying to open appears to be corrupted. Try downloading it again." : { + "string" : "Ljudboken som du försöker öppna verkar vara skadad. Försöka ladda ner den på nytt." + }, + "The book license has expired." : { + "string" : "Bokens licens har löpt ut." + }, + "The book you were trying to open is invalid." : { + "string" : "Boken som du försökte öppna är ogiltig." + }, + "The book you were trying to read is corrupted. Please try downloading it again." : { + "string" : "Boken som du försökte läsa är skadad. Försök ladda ner den på nytt." + }, + "The book you were trying to read is in an unsupported format." : { + "string" : "Boken som du försöker läsa har ett format som inte stöds." + }, + "The download could not be completed." : { + "string" : "Nedladdningen kunde inte slutföras." + }, + "The download could not be completed.\nScroll down to 'View Issues' to see details." : { + "string" : "Nedladdningen kunde inte slutföras.\nScrolla ner till Visa problem för mer information." + }, + "The download for %@ could not be completed." : { + "string" : "Nedladdningen av %@ kunde inte slutföras." + }, + "The item you are trying to open is not currently supported." : { + "string" : "Objektet du försöker öppna stöds inte för närvarande." + }, + "The page could not load due to a conection error." : { + "string" : "Sidan kunde inte laddas på grund av ett anslutningsfel." + }, + "The page could not load due to a connection error." : { + "string" : "Sidan kunde inte laddas på grund av ett anslutningsfel." + }, + "The return of %@ could not be completed." : { + "string" : "Det gick inte att returnera %@." + }, + "The title you reserved, (book.title), is available." : { + "string" : "Titeln du reserverat, (book.title), är tillgänglig." + }, + "There are no bookmarks for this book." : { + "string" : "Det finns inga bokmärken för denna bok." + }, + "There are no results" : { + "string" : "Inga resutlat" + }, + "There was a problem contacting the server.\nPlease make sure you are connected to the internet, or try again later." : { + "string" : "Det uppstod ett fel när servern anropades.\nKontrollera att du är uppkopplad till internet eller försök på nytt senare." + }, + "This URL cannot be found. Please close the app entirely and reload it. If the problem persists, please contact your library's Help Desk." : { + "string" : "Kunde inte hitta denna URL. Stäng appen helt och starta om den. Om problemet fortsätter, kontakta ditt biblioteks supportavdelning." + }, + "This book is available to borrow." : { + "string" : "Denna bok är tillgänglig för utlåning." + }, + "This reservation will be automatically cancelled in %@." : { + "string" : "Denna reservation återkallas automatiskt om %@." + }, + "Three quarters of normal speed. Slower." : { + "string" : "Tre fjärdedelar av normal hastighet. Långsammare." + }, + "Title" : { + "string" : "Titel" + }, + "Track %@" : { + "string" : "Spår %@" + }, + "Translators" : { + "string" : "" + }, + "Try Again" : { + "string" : "Försök på nytt" + }, + "Try force-quitting the app and repeat the sign-in process." : { + "string" : "Försök tvinga avstängning av appen och upprepa inloggningsprocessen." + }, + "Two times normal speed. Fastest." : { + "string" : "Dubbel hastighet. Snabbast." + }, + "Unable to contact the server because the URL for signing in is missing." : { + "string" : "Det gick inte att kontakta servern på grund av att URL för inloggning saknas." + }, + "Unable to load PDF file" : { + "string" : "Det går inte att ladda PDF-filen" + }, + "Unable to load the web page at this time." : { + "string" : "Det går inte att ladda webbsidan just nu." + }, + "Under 13" : { + "string" : "Under 13" + }, + "Unkown error occurred. Please try again." : { + "string" : "Det har uppstått ett okänt fel. Försök på nytt." + }, + "Unsupported Item" : { + "string" : "Objektet stöds inte" + }, + "Unsupported format" : { + "string" : "Formatet stöds inte" + }, + "User Agreement" : { + "string" : "Användaravtal" + }, + "User denied location access. Go to system settings to enable location access for E-kirjasto." : { + "string" : "Positionsåtkomst nekad av användaren. Gå till systeminställningarna för att ge E-biblioteket positionsåtkomst." + }, + "User denied location access. Go to system settings to enable location access for the Palace App." : { + "string" : "Positionsåtkomst nekad av användaren. Gå till systeminställningarna för att ge Palace-appen positionsåtkomst." + }, + "Username:" : { + "string" : "" + }, + "Verifying" : { + "string" : "Verifierar" + }, + "View Sample" : { + "string" : "Visa utdrag" + }, + "View sample for %@" : { + "string" : "Visa utdrag ur %@" + }, + "Visit the Catalog to\nadd books to My Books." : { + "string" : "Besök katalogen för att\nlägga till böcker i Mina böcker." + }, + "WAITING FOR AVAILABILITY" : { + "string" : "VÄNTAR PÅ TILLGÄNGLIGHET" + }, + "Wait" : { + "string" : "Vänta" + }, + "We can’t get your library right now. Please close and reopen the app to try again." : { + "string" : "Vi kan inte hämta ditt bibliotek just nu. Stäng och starta om appen för att försöka på nytt." + }, + "We're sorry. Currently we do not support signups for new patrons via the app." : { + "string" : "Vi beklagar. För närvarande stöds inte registrering av nya kunder via appen." + }, + "We're sorry. Our sign up system is currently down. Please try again later." : { + "string" : "Vi beklagar. Vårt registreringssystem ligger nere just nu. Försök på nytt senare." + }, + "Welcome to Open eBooks" : { + "string" : "Välkommen till Open eBooks" + }, + "When you reserve a book from the catalog, it will show up here. Look here from time to time to see if your book is available to download." : { + "string" : "När du reserverar en bok från katalogen kommer den att visas här. Titta in här då och då för att se om din bok kan laddas ner." + }, + "White on black text" : { + "string" : "Vit text på svart bakgrund" + }, + "Would you like to return it?" : { + "string" : "Vill du lämna den tillbaka?" + }, + "You are %ld in line for %ld copies." : { + "string" : "Du är på plats %1$ld i kö för %2$ld kopior." + }, + "You are %ld in line." : { + "string" : "Du är på plats %ld i kön." + }, + "You have already checked out this loan. You may need to refresh your My Books list to download the title." : { + "string" : "Du har redan lånat denna bok. Det kan hända att du måste uppdatera listan i Mina böcker för att ladda ner titeln." + }, + "You have disabled location services for this app." : { + "string" : "Du har inaktiverat positionstjänster för denna app." + }, + "You must enable camera access for this application in order to sign up for a library card." : { + "string" : "Du måste tillåta kameraåtkomst för denna app för att registrera dig för ett bibliotekskort." + }, + "You need to login to access the collection." : { + "string" : "Du måste logga in för att komma åt samlingen." + }, + "Your Audiobook Has Finished" : { + "string" : "Din ljudbok har spelat till slut" + }, + "Your authentication details have expired. Please sign in again." : { + "string" : "Dina autentiseringsuppgifter har löpt ut. Logga in på nytt." + }, + "Your book has not yet been downloaded." : { + "string" : "Din bok har ännu inte laddats ner." + }, + "Your book is ready to read!" : { + "string" : "Din bok är redo att läsas!" + }, + "Your bookmarks and reading positions are in the process of being saved to the server. Would you like to stop that and continue logging out?" : { + "string" : "Dina bokmärken och läspositioner håller på att sparas på servern. Vill du stoppa processen och fortsätta med att logga ut?" + }, + "Your report will be reviewed as soon as possible." : { + "string" : "Din rapport kommer att behandlas så snart som möjligt." + }, + "accessibilityShowAndReloadCatalogTab" : { + "string" : "accessibilityShowAndReloadCatalogTab" + }, + "currently" : { + "string" : "nu" + }, + "day_suffix_long" : { + "string" : "{???, plural, one {1 dag} other {%d dagar}}" + }, + "day_suffix_short" : { + "string" : "{???, plural, one {1 d} other {%d d}}" + }, + "eCard" : { + "string" : "eCard" + }, + "ePub" : { + "string" : "ePub" + }, + "hour_suffix_long" : { + "string" : "{???, plural, one {1 timme} other {%d timmar}}" + }, + "hour_suffix_short" : { + "string" : "{???, plural, one {1 h} other {%d h}}" + }, + "month_suffix_long" : { + "string" : "{???, plural, one {1 månad} other {%d månader}}" + }, + "month_suffix_short" : { + "string" : "{???, plural, one {1 m} other {%d m}}" + }, + "sec" : { + "string" : "sek" + }, + "week_suffix_long" : { + "string" : "{???, plural, one {1 vecka} other {%d veckor}}" + }, + "week_suffix_short" : { + "string" : "{???, plural, one {1 v} other {%d v}}" + }, + "year_suffix_long" : { + "string" : "{???, plural, one {1 år} other {%d år}}" + }, + "year_suffix_short" : { + "string" : "{???, plural, one {1 år} other {%d år}}" + } + } +} diff --git a/PalaceConfig/GoogleService-Info.plist.example b/PalaceConfig/GoogleService-Info.plist similarity index 59% rename from PalaceConfig/GoogleService-Info.plist.example rename to PalaceConfig/GoogleService-Info.plist index d28e0da62..2b1b6a1c2 100644 --- a/PalaceConfig/GoogleService-Info.plist.example +++ b/PalaceConfig/GoogleService-Info.plist @@ -2,22 +2,18 @@ - CLIENT_ID - {CLIENT_ID}.apps.googleusercontent.com - REVERSED_CLIENT_ID - com.googleusercontent.apps.{CLIENT_ID} API_KEY - {API_KEY} + AIzaSyCfo40mW9UVcWxT0Cs4e31cP2h-djFRdLc GCM_SENDER_ID - {GCM_SENDER_ID} + 706915474057 PLIST_VERSION 1 BUNDLE_ID - {BUNDLE_ID} + fi.kansalliskirjasto.e-kirjasto PROJECT_ID - {PROJECT_ID} + e-kirjasto STORAGE_BUCKET - {STORAGE_BUCKET} + e-kirjasto.appspot.com IS_ADS_ENABLED IS_ANALYTICS_ENABLED @@ -29,8 +25,6 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - {GOOGLE_APP_ID} - DATABASE_URL - {DATABASE_URL} + 1:706915474057:ios:32e48c986086d0a1378458 \ No newline at end of file diff --git a/PalaceR2.xcworkspace/xcshareddata/swiftpm/Package.resolved b/PalaceR2.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 732b22a8d..000000000 --- a/PalaceR2.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,104 +0,0 @@ -{ - "pins" : [ - { - "identity" : "cryptoswift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", - "state" : { - "revision" : "039f56c5d7960f277087a0be51f5eb04ed0ec073", - "version" : "1.5.1" - } - }, - { - "identity" : "differencekit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ra1028/DifferenceKit.git", - "state" : { - "revision" : "073b9671ce2b9b5b96398611427a1f929927e428", - "version" : "1.3.0" - } - }, - { - "identity" : "fuzi", - "kind" : "remoteSourceControl", - "location" : "https://github.com/cezheng/Fuzi.git", - "state" : { - "revision" : "f08c8323da21e985f3772610753bcfc652c2103f", - "version" : "3.1.3" - } - }, - { - "identity" : "gcdwebserver", - "kind" : "remoteSourceControl", - "location" : "https://github.com/readium/GCDWebServer.git", - "state" : { - "revision" : "c7bdaa9892e06477d21819e99540ae13fcfa25f2", - "version" : "3.7.4" - } - }, - { - "identity" : "purelayout", - "kind" : "remoteSourceControl", - "location" : "https://github.com/PureLayout/PureLayout", - "state" : { - "revision" : "5561683c96dc49b023c1299bfe4f6fbeed5f8199", - "version" : "3.1.9" - } - }, - { - "identity" : "sqlite.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/stephencelis/SQLite.swift.git", - "state" : { - "revision" : "5f5ad81ac0d0a0f3e56e39e646e8423c617df523", - "version" : "0.13.2" - } - }, - { - "identity" : "swift-toolkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/readium/swift-toolkit.git", - "state" : { - "revision" : "9e0339787aa69f96bb16335f55a858d626eaccb9", - "version" : "2.5.0" - } - }, - { - "identity" : "swiftsoup", - "kind" : "remoteSourceControl", - "location" : "https://github.com/scinfu/SwiftSoup.git", - "state" : { - "revision" : "f707b8680cddb96dc1855632340a572ef37bbb98", - "version" : "2.5.3" - } - }, - { - "identity" : "transifex-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/transifex/transifex-swift/", - "state" : { - "revision" : "e983af3184c456f6061620667a455aa95e99df32", - "version" : "1.0.2" - } - }, - { - "identity" : "zip", - "kind" : "remoteSourceControl", - "location" : "https://github.com/marmelroy/Zip.git", - "state" : { - "revision" : "67fa55813b9e7b3b9acee9c0ae501def28746d76", - "version" : "2.1.2" - } - }, - { - "identity" : "zipfoundation", - "kind" : "remoteSourceControl", - "location" : "https://github.com/weichsel/ZIPFoundation.git", - "state" : { - "revision" : "ec32d62d412578542c0ffb7a6ce34d3e64b43b94", - "version" : "0.9.11" - } - } - ], - "version" : 2 -} diff --git a/RDServices.xcodeproj/project.pbxproj b/RDServices.xcodeproj/project.pbxproj index cbcbe07db..9a345abd5 100644 --- a/RDServices.xcodeproj/project.pbxproj +++ b/RDServices.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -673,6 +673,546 @@ }; name = Release; }; + 260CAD812C1A3B3B00BD54C6 /* Debug-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + WARNING_CFLAGS = "-w"; + }; + name = "Debug-ellibs"; + }; + 260CAD822C1A3B3B00BD54C6 /* Debug-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Debug-ellibs"; + }; + 260CAD852C1A3B4300BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + WARNING_CFLAGS = "-w"; + }; + name = "Debug-dev"; + }; + 260CAD862C1A3B4300BD54C6 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Debug-dev"; + }; + 260CAD872C1A3B4C00BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + WARNING_CFLAGS = "-w"; + }; + name = "Debug-beta"; + }; + 260CAD882C1A3B4C00BD54C6 /* Debug-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Debug-beta"; + }; + 260CAD892C1A3B5300BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + WARNING_CFLAGS = "-w"; + }; + name = "Debug-production"; + }; + 260CAD8A2C1A3B5300BD54C6 /* Debug-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Debug-production"; + }; + 260CAD8B2C1A3B5C00BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = "-w"; + }; + name = "Release-ellibs"; + }; + 260CAD8C2C1A3B5C00BD54C6 /* Release-ellibs */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Release-ellibs"; + }; + 260CAD8D2C1A3B6B00BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = "-w"; + }; + name = "Release-dev"; + }; + 260CAD8E2C1A3B6B00BD54C6 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Release-dev"; + }; + 260CAD8F2C1A3B7600BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = "-w"; + }; + name = "Release-beta"; + }; + 260CAD902C1A3B7600BD54C6 /* Release-beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Release-beta"; + }; + 260CAD912C1A3B7C00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "${SDKROOT}/usr/include/libxml2", + "\"$(SRCROOT)/readium-sdk/Platform/Apple/include\"/**", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/dp/public\"", + "\"$(NYPLADEPT_ADOBE_SDK)/DRM_Connector_Prerelease/xml/uft/public\"", + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = "-w"; + }; + name = "Release-production"; + }; + 260CAD922C1A3B7C00BD54C6 /* Release-production */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/RDServices.dst; + HEADER_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = "Release-production"; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -680,7 +1220,15 @@ isa = XCConfigurationList; buildConfigurations = ( 118A0E491992B3FD00792DDE /* Debug */, + 260CAD812C1A3B3B00BD54C6 /* Debug-ellibs */, + 260CAD852C1A3B4300BD54C6 /* Debug-dev */, + 260CAD872C1A3B4C00BD54C6 /* Debug-beta */, + 260CAD892C1A3B5300BD54C6 /* Debug-production */, 118A0E4A1992B3FD00792DDE /* Release */, + 260CAD8B2C1A3B5C00BD54C6 /* Release-ellibs */, + 260CAD8D2C1A3B6B00BD54C6 /* Release-dev */, + 260CAD8F2C1A3B7600BD54C6 /* Release-beta */, + 260CAD912C1A3B7C00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -689,7 +1237,15 @@ isa = XCConfigurationList; buildConfigurations = ( 118A0E4C1992B3FD00792DDE /* Debug */, + 260CAD822C1A3B3B00BD54C6 /* Debug-ellibs */, + 260CAD862C1A3B4300BD54C6 /* Debug-dev */, + 260CAD882C1A3B4C00BD54C6 /* Debug-beta */, + 260CAD8A2C1A3B5300BD54C6 /* Debug-production */, 118A0E4D1992B3FD00792DDE /* Release */, + 260CAD8C2C1A3B5C00BD54C6 /* Release-ellibs */, + 260CAD8E2C1A3B6B00BD54C6 /* Release-dev */, + 260CAD902C1A3B7600BD54C6 /* Release-beta */, + 260CAD922C1A3B7C00BD54C6 /* Release-production */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/README-Palace.md b/README-Palace.md new file mode 100644 index 000000000..1604ceb07 --- /dev/null +++ b/README-Palace.md @@ -0,0 +1,76 @@ +![Palace Build](https://github.com/ThePalaceProject/ios-core/actions/workflows/upload-on-merge.yml/badge.svg) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +# The Palace Project + +This repository contains the client-side code for The Palace Project [Palace](https://thepalaceproject.org) application. + +# System Requirements + +- Install Xcode 14.2 in `/Applications`, open it and make sure to install additional components if it asks you. +- Install [Carthage](https://github.com/Carthage/Carthage) if you haven't already. Using `brew` is recommended. + +If you run this project **with DRM support** on a Mac computer with Apple Silicon, make sure to check **[x] Open using Rosetta** in Xcode.app application info. This is required to build with Adobe DRM support. + +# Building without Adobe DRM nor Private Repos + +```bash +git clone git@github.com:ThePalaceProject/ios-core.git +cd ios-core + +# one-time set-up +./scripts/setup-repo-nodrm.sh + +# idempotent script to rebuild all dependencies +./scripts/build-3rd-party-dependencies.sh --no-private +``` +Open `Palace.xcodeproj` and build the `Palace-noDRM` target. + +At this point you may have seemingly random build errors especially if you are +not using an intel chip but the following steps might help: + +`ln -s $(which carthage) /usr/local/bin/carthage` +Remove all files under `~/Library/Developer/Xcode/DerivedData/*` +⇧⌘K Clean Build Folder + +# Building With Adobe DRM + +## Building the Application from Scratch + +01. Contact project lead and ensure you have access to all the required private repos. +02. Then run: +```bash +git clone git@github.com:ThePalaceProject/ios-core.git +cd ios-core +./scripts/bootstrap-drm.sh +``` +03. Open Palace.xcodeproj and build the `Palace` target. + +## Building Dependencies Individually + +Unless the DRM dependencies change (which is very seldom) you shouldn't need to run the `bootstrap-drm.sh` script more than once. + +Other 3rd party dependencies are managed via Carthage and a few git submodules. To rebuild them you can use the following idempotent script: +```bash +cd ios-core +./scripts/build-3rd-party-dependencies.sh +``` +The `scripts` directory contains a number of other scripts to build dependencies more granularly and also to build/archive/test the app from the command line. These scripts are the same used by our CI system. All these scripts must be run from the root of Palace `ios-core` repository, not from the `scripts` directory. + +## Branching and CI + +`develop` is the main development branch. + +Release branch names follow the convention: `release/palace/`. For example, `release/palace/1.0.0`. + +Feature branch names (for features whose development is a month or more): `feature/`, e.g. `feature/my-new-screen`. + +Continuous integration is enabled on merge events on `develop` branch. Palace device builds are uploaded to [ios-binaries](https://github.com/ThePalaceProject/ios-binaries). + +# Palace License + +Copyright © 2021 LYRASIS + +Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, +WITHOUT 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 index 1604ceb07..2279adac5 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,105 @@ -![Palace Build](https://github.com/ThePalaceProject/ios-core/actions/workflows/upload-on-merge.yml/badge.svg) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +# E-kirjasto iOS core -# The Palace Project +[![ios-main](https://github.com/NatLibFi/ekirjasto-ios-core/actions/workflows/ios-main.yml/badge.svg)](https://github.com/NatLibFi/ekirjasto-ios-core/actions/workflows/ios-main.yml) -This repository contains the client-side code for The Palace Project [Palace](https://thepalaceproject.org) application. +The National Library of Finland's fork of the Palace Project iOS client, +which is itself the Lyrasis fork of the NYPL's Library Simplified iOS client. -# System Requirements -- Install Xcode 14.2 in `/Applications`, open it and make sure to install additional components if it asks you. -- Install [Carthage](https://github.com/Carthage/Carthage) if you haven't already. Using `brew` is recommended. +## System requirements -If you run this project **with DRM support** on a Mac computer with Apple Silicon, make sure to check **[x] Open using Rosetta** in Xcode.app application info. This is required to build with Adobe DRM support. +- Install Xcode 15.4 in `/Applications`, open it and make sure to install additional components if it asks you. +- Install [Carthage](https://github.com/Carthage/Carthage) if you haven't already. + - Using Homebrew is recommended, so run `brew install carthage`. -# Building without Adobe DRM nor Private Repos -```bash -git clone git@github.com:ThePalaceProject/ios-core.git -cd ios-core +## Building -# one-time set-up -./scripts/setup-repo-nodrm.sh +```bash +git clone git@github.com:NatLibFi/ekirjasto-ios-core.git +cd ekirjasto-ios-core -# idempotent script to rebuild all dependencies -./scripts/build-3rd-party-dependencies.sh --no-private +# Idempotent bootstrap script, can be run again to rebuild dependencies +./scripts/bootstrap.sh ``` -Open `Palace.xcodeproj` and build the `Palace-noDRM` target. -At this point you may have seemingly random build errors especially if you are -not using an intel chip but the following steps might help: +The above bootstrap script also reveals secrets for production builds. +For more info, see `./scripts/reveal-secrets.sh --help`. -`ln -s $(which carthage) /usr/local/bin/carthage` -Remove all files under `~/Library/Developer/Xcode/DerivedData/*` -⇧⌘K Clean Build Folder +Open `Palace.xcodeproj` in Xcode and build the `Ekirjasto` target. -# Building With Adobe DRM +Alternatively, you can build the app by running `./scripts/build.sh` +(use `--help` to see build options). -## Building the Application from Scratch +At this point you may have seemingly random build errors especially if you are +not using an Intel chip (M1/M2/M3/etc.) but running this script might help: -01. Contact project lead and ensure you have access to all the required private repos. -02. Then run: ```bash -git clone git@github.com:ThePalaceProject/ios-core.git -cd ios-core -./scripts/bootstrap-drm.sh +# Requires sudo, because it also cleans ~/Library/Developer/Xcode/DerivedData/ +./scripts/clean.sh ``` -03. Open Palace.xcodeproj and build the `Palace` target. -## Building Dependencies Individually +If you get `Missing package product '...'` errors, +closing and reopening the Xcode project should help. -Unless the DRM dependencies change (which is very seldom) you shouldn't need to run the `bootstrap-drm.sh` script more than once. -Other 3rd party dependencies are managed via Carthage and a few git submodules. To rebuild them you can use the following idempotent script: -```bash -cd ios-core -./scripts/build-3rd-party-dependencies.sh -``` -The `scripts` directory contains a number of other scripts to build dependencies more granularly and also to build/archive/test the app from the command line. These scripts are the same used by our CI system. All these scripts must be run from the root of Palace `ios-core` repository, not from the `scripts` directory. +### Build configurations + +The app uses build configurations to switch the backend. +The configurations are of the form `-`, +so for example `Debug-dev` is a debug build using the `dev` configuration/backend. + +The available configurations are: + +| Configuration | Build type | Backend | +|--------------------|------------|------------| +| Debug | debug | production | +| Debug-ellibs | debug | ellibs | +| Debug-dev | debug | dev | +| Debug-beta | debug | beta | +| Debug-production | debug | production | +| Release | release | production | +| Release-ellibs | release | ellibs | +| Release-dev | release | dev | +| Release-beta | release | beta | +| Release-production | release | production | + +The `Debug` and `Debug-production` are essentially identical, +and they both use the `production` backend. +The same is true for `Release` and `Release-production`. + +The `Debug` and `Release` configurations are there only for "compatibility", +because some tools (like Carthage) appear to not work nicely if they don't exist, +but you shouldn't need to *use* them (just don't delete them). + +To choose the build configuration to use in Xcode, +`Alt-click` the "Run" button and choose which one to use for running, profiling, etc. + + +## Branching + +`main` is the main development branch, and is only updated through pull requests. + +Release branch names follow the convention: `release/` (e.g. `release/1.2.3`). + + +## Continuous integration (CI) + +The repository uses continuous integration to aid development and to automate releases. -## Branching and CI +See [.github/workflows/README.md] for more information about the CI workflows. -`develop` is the main development branch. -Release branch names follow the convention: `release/palace/`. For example, `release/palace/1.0.0`. +## Releasing -Feature branch names (for features whose development is a month or more): `feature/`, e.g. `feature/my-new-screen`. +Please see [RELEASING.md](RELEASING.md) for documentation on E-kirjasto's release process. -Continuous integration is enabled on merge events on `develop` branch. Palace device builds are uploaded to [ios-binaries](https://github.com/ThePalaceProject/ios-binaries). -# Palace License +## License -Copyright © 2021 LYRASIS +Copyright © 2021 LYRASIS and The National Library of Finland (Kansalliskirjasto) -Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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/RELEASING-Palace.md b/RELEASING-Palace.md new file mode 100644 index 000000000..83fa74b72 --- /dev/null +++ b/RELEASING-Palace.md @@ -0,0 +1,81 @@ +# Releasing + +Palace release process is automated and relies on Github workflow scripts. Workflow scripts create a new build every time a pull request is merged to the `develop` branch, make a new release on Github, and upload a new binary to Test Flight. + +## Development Process + +`develop` is the main development branch. + +Every new feature, bug fix or other task are developed on branches named following this naming convention: + +- `feature/name` for new features; +- `fix/name` for bug fixes; +- `task/name` for miscellaneous tasks. + +## Github Actions and the Release Process + +### Palace Build + +Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/upload-on-merge.yml) + +Starts on merge to `develop` branch. + +The script performs several steps: + +- checks the project build version - if the version remains the same, the action stops; it helps to avoid unnecessary builds when updates are not related to the project itself, for example, changes in a CI script should not result in a new binary on Test Flight; +- generates release notes for Test Flight "What to Test" description; +- uploads a new build to Test Flight. + +### Palace Manual Build + +Location: [.github/workflows/upload.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/upload.yml) + +This script is similar to "Palace Build", but can be started manually. Performs the same set of steps. + +### Palace Release + +Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/release-on-merge.yml) + +Starts on merge to `main` branch. + +The script performs several steps: + +- generates release notes for a new release on Github; +- creates a new release on Github. + +### Palace Manual Release + +Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/release.yml) + +This script is similar to "Palace Release", but can be started manually. Performs the same set of steps. + +### Unit Tests + +Location: [.github/workflows/unit-testing.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/unit-testing.yml) + +Starts on pull request, can be started manually. + +The script builds the project and runs unit tests. + +## Release notes + +We use a custom script to generate release notes. The script can be found in the `mobile-certificates` repository, [Certificates/Palace/iOS/ReleaseNotes.py](https://github.com/ThePalaceProject/mobile-certificates/blob/master/Certificates/Palace/iOS/ReleaseNotes.py). + +The script collects titles of pull requests that were merged between releases, links to pull requests and links to Notion tickets, mentioned in the pulls. + +Usage: + +```python +python3 ReleaseNotes.py [-t TAG] [-v VERBOSITY] +``` + +where: + +- -t TAG, --tag TAG: tag to start collecting release notes from. If omitted, collects from the latest tag available. +- -v VERBOSITY, --verbosity VERBOSITY: how much information to show: + - 1 (default) - pull title only; + - 2 - title and links to PR and Notion ticket, markdown + format; + - 3 - title and Notion ticket link, when available + +The `ios-core` repository contains [scripts/release-notes.sh](https://github.com/ThePalaceProject/ios-core/blob/develop/scripts/release-notes.sh) file that installs `request` module first (by default, not available on Github CI images). \ No newline at end of file diff --git a/RELEASING.md b/RELEASING.md index 83fa74b72..7b57d3545 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,81 +1,120 @@ # Releasing -Palace release process is automated and relies on Github workflow scripts. Workflow scripts create a new build every time a pull request is merged to the `develop` branch, make a new release on Github, and upload a new binary to Test Flight. +Releasing of the E-kirjasto Android app is mostly automated through a CI workflow. -## Development Process -`develop` is the main development branch. +## The short version (TL;DR) -Every new feature, bug fix or other task are developed on branches named following this naming convention: +- Create a release branch, for example `release/1.2.3` + - Update the version by running e.g. `./scripts/release.sh --set-version 1.2.3` + - Fill in the changelogs at `metadata//changelog.txt` +- In GitHub Actions, check that the build and all checks will pass + - If something fails, the build will not be uploaded to App Store Connect +- Once the build is uploaded to App Store Connect + - Promote the build to production + - Send the release for app review + - After the app passes review, it can be published -- `feature/name` for new features; -- `fix/name` for bug fixes; -- `task/name` for miscellaneous tasks. -## Github Actions and the Release Process +## Version numbers -### Palace Build +The script at `scripts/version.sh` should be used to manage the version number. +See the script's `--help` option for mode information. -Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/upload-on-merge.yml) +The version number should follow the [Semantic Versioning](https://semver.org/) format. +Basically, the version number is of the form `major.minor.patch`. +App Store Connect doesn't allow any suffix in the version, so they can't be used. -Starts on merge to `develop` branch. +The version number should be incremented as follows: +- the `major` component should increase for any major new functionality + - the `major` component should also increase for any non-backward-compatible changes + - if the `major` component increases, both `minor` and `patch` are "reset" to zero + - for example, `1.2.3` becomes `2.0.0` when increasing the `major` component +- the `minor` component should increase for any new features + - if the `minor` component increases, `patch` is "reset" to zero + - for example, `1.2.3` becomes `1.3.0` when increasing the `minor` component +- the patch version should increase for bugfixes and other minor changes +- the version components should not have any leading zeroes +- the version components can have multiple digits (e.g. 1.0.9 can increase to 1.0.10) -The script performs several steps: -- checks the project build version - if the version remains the same, the action stops; it helps to avoid unnecessary builds when updates are not related to the project itself, for example, changes in a CI script should not result in a new binary on Test Flight; -- generates release notes for Test Flight "What to Test" description; -- uploads a new build to Test Flight. +## Build numbers -### Palace Manual Build +The script at `scripts/version.sh` should be used to manage the build number. +See the script's `--help` option for mode information. -Location: [.github/workflows/upload.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/upload.yml) +That said, you shouldn't have to modify the build number at all, +since it is automatically increased on every upload to App Store Connect / Testflight. -This script is similar to "Palace Build", but can be started manually. Performs the same set of steps. +Based on the build configuration, the last digit of the build number is set to: -### Palace Release +| Configuration | Last digit in version code | +|---------------|----------------------------| +| production | 1 | +| beta | 2 | +| dev | 3 | +| ellibs | 4 | -Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/release-on-merge.yml) +This way all different build configurations of the same build/commit can be uploaded to App Store Connect. +But note that the different configurations should be uploaded in the above order, so that the other digits apart from the last will match for the same build/commit. -Starts on merge to `main` branch. -The script performs several steps: +## Creating a new release -- generates release notes for a new release on Github; -- creates a new release on Github. +### Building and uploading to App Store Connect -### Palace Manual Release +#### Automated CI workflow (recommended) -Location: [.github/workflows/upload-on-merge.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/release.yml) +To create a new release, create a branch of the form `release/`. +For example, the release branch name could be `release/1.2.3` or `release/3.20.1-suffix`. -This script is similar to "Palace Release", but can be started manually. Performs the same set of steps. +Increase the version number by running something like: +- `./scripts/version.sh --set-version 1.2.3` -### Unit Tests +Edit these files for the changelog (will be visible to users in App Store / Testflight): +- `metadata//changelog.txt` -Location: [.github/workflows/unit-testing.yml](https://github.com/ThePalaceProject/ios-core/blob/main/.github/workflows/unit-testing.yml) +When a release branch is created, the `ios-release` workflow: +- performs release checks + - the version number must increase from the main branch + - there must not be any uncommitted Transifex strings + - these should be downloaded using `./scripts/transifex.sh` + - see `--help` for setting the Transifex token and secret +- builds both debug and release builds for all flavors +- uploads the release build to App Store Connect / Testflight -Starts on pull request, can be started manually. +If the release checks and everything else in the CI workflow goes okay, +the release build will be uploaded to App Store Connect / Testflight. -The script builds the project and runs unit tests. -## Release notes +#### Manual build and upload -We use a custom script to generate release notes. The script can be found in the `mobile-certificates` repository, [Certificates/Palace/iOS/ReleaseNotes.py](https://github.com/ThePalaceProject/mobile-certificates/blob/master/Certificates/Palace/iOS/ReleaseNotes.py). +Alternatively, the release process can be done manually. -The script collects titles of pull requests that were merged between releases, links to pull requests and links to Notion tickets, mentioned in the pulls. +In order to perform a release build, you need: +- run `./scripts/bootstrap.sh` with the secret environment variables set + - run `./scripts/reveal-secrets.sh --help` for a list of the environemnt variables +- the certificates and provisioning profiles for signing the build + - these are stored in the `ekirjasto-ios-keys` repository, so you need access there + - the keys are managed by Fastlane, and you will need the encryption password to use them + - to get the keys from the repo, run `fastlane match` and follow the instructions -Usage: +First, update the version number using `./scripts/version.sh --set-version x.y.z`. -```python -python3 ReleaseNotes.py [-t TAG] [-v VERBOSITY] -``` +Then, build the release version of the production flavor: +- either by running `./scripts/build.sh release` +- or manually in Xcode (via `Product` > `Archive`) -where: +Once you've built the release archive, you can upload it to App Store Connect: +- either by running `./scripts/build.sh release_upload` + - this also builds the release archive, so you don't have to run `build.sh release` separately + - this defaults to the `production` config, but you can add e.g. `configuration:beta` to the command to use another backend +- or create a new version and upload it manually in App Store Connect -- -t TAG, --tag TAG: tag to start collecting release notes from. If omitted, collects from the latest tag available. -- -v VERBOSITY, --verbosity VERBOSITY: how much information to show: - - 1 (default) - pull title only; - - 2 - title and links to PR and Notion ticket, markdown - format; - - 3 - title and Notion ticket link, when available -The `ios-core` repository contains [scripts/release-notes.sh](https://github.com/ThePalaceProject/ios-core/blob/develop/scripts/release-notes.sh) file that installs `request` module first (by default, not available on Github CI images). \ No newline at end of file +### Publishing an uploaded build + +Once a release build archive is uploaded to App Store Connect, +you can promote it to a production version and send it for app review. + +Assuming review passes, the app can be published to production! diff --git a/fastlane/.gitignore b/fastlane/.gitignore new file mode 100644 index 000000000..49f63be59 --- /dev/null +++ b/fastlane/.gitignore @@ -0,0 +1,5 @@ +# Ignore App Store Connect API keys +*.p8 +*api*.json +*key*.json + diff --git a/fastlane/Appfile b/fastlane/Appfile index a841b95b0..f0ba71ae8 100644 --- a/fastlane/Appfile +++ b/fastlane/Appfile @@ -5,4 +5,3 @@ team_id "QA5XMCRV5M" app_identifier "fi.kansalliskirjasto.e-kirjasto" - diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 86f870b32..726e24973 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,17 +1,84 @@ +# This file contains the fastlane.tools configuration +# You can find the documentation at https://docs.fastlane.tools +# +# For a list of all available actions, check out +# +# https://docs.fastlane.tools/actions +# +# For a list of all available plugins, check out +# +# https://docs.fastlane.tools/plugins/available-plugins +# https://docs.fastlane.tools/actions/build_app/ + +# +# Get changelog text (for a given language). +# +def get_changelog(language = "en-US") + filepath = "../metadata/#{language}/changelog.txt" + contents = File.read(filepath) + contents.strip! + return contents +end + +# +# Check if a build configuration is valid. +# +def is_build_configuration_valid(configuration) + return ["ellibs", "dev", "beta", "production"].include?(configuration) +end + +# +# Get build configuration from options. +# +def options_configuration(options) + configuration = (options[:config] ? options[:config] : "production") + unless is_build_configuration_valid(configuration) + UI.user_error!("ERROR: Invalid build configuration name: #{configuration}") + end + return configuration +end + + +# Uncomment the line if you want fastlane to automatically update itself +#update_fastlane + default_platform(:ios) platform :ios do + desc "Print the latest build number from Testflight" + lane :print_testflight_build_number do |options| + build_number_max = latest_testflight_build_number( + api_key_path: "fastlane/app-store-connect-api-key.json", + # Set initial build number to 10000, like in the project + initial_build_number: 10000 + ) + puts "\n\nTESTFLIGHT_BUILD_NUMBER_MAX=#{build_number_max.to_i()}\n" + end + + desc "Run tests" lane :test do run_tests( project: "Palace.xcodeproj", - devices: ["iPhone 12 Pro"], + devices: ["iPhone 12 Pro"], # TODO:SAMI: Change to iPhone 15 Pro? scheme: "Ekirjasto" ) end - lane :nodrm do |options| + + desc "Run a debug build" + lane :build_debug do |options| + configuration = options_configuration(options) + puts "Build configuration: #{configuration}" + + setup_ci#(force: true) + match( + type: "adhoc", + readonly: true, + app_identifier: "fi.kansalliskirjasto.e-kirjasto" + ) build_app( project: "Palace.xcodeproj", scheme: "Ekirjasto", + configuration: "Debug-#{configuration}", skip_package_ipa: true, skip_archive: true, skip_codesigning: true, @@ -24,40 +91,74 @@ platform :ios do } ) end - lane :beta do |options| + + desc "Run a release build" + lane :build_release do |options| + configuration = options_configuration(options) + puts "Build configuration: #{configuration}" + + #setup_ci#(force: true) + match( + type: "adhoc", + readonly: true, + app_identifier: "fi.kansalliskirjasto.e-kirjasto" + ) build_app( project: "Palace.xcodeproj", scheme: "Ekirjasto", + configuration: "Release-#{configuration}", include_symbols: true, include_bitcode: false, silent: true, - output_name: options[:output_name], - output_directory: options[:export_path], - export_options: { - method: "ad-hoc", - provisioningProfiles: { - "fi.kansalliskirjasto.e-kirjasto" => "Ad Hoc" - } - } + #output_name: options[:output_name], + #output_directory: options[:export_path], + #export_options: { + # method: "ad-hoc", + # provisioningProfiles: { + # "fi.kansalliskirjasto.e-kirjasto" => "Ad Hoc" + # } + #} ) end - lane :appstore do |options| + + desc "Run a release build and upload to TestFlight" + lane :build_release_upload do |options| + configuration = options_configuration(options) + puts "Build configuration: #{configuration}" + default_changelog = get_changelog() + puts "Changelog:\n#{default_changelog}" + + setup_ci#(force: true) + match( + type: "appstore", + readonly: true, + app_identifier: "fi.kansalliskirjasto.e-kirjasto" + ) build_app( project: "Palace.xcodeproj", scheme: "Ekirjasto", + configuration: "Release-#{configuration}", include_symbols: true, include_bitcode: false, - export_options: { - method: "app-store", - provisioningProfiles: { - "fi.kansalliskirjasto.e-kirjasto" => "App Store" - } - } + #export_options: { + # method: "app-store", + # provisioningProfiles: { + # "fi.kansalliskirjasto.e-kirjasto" => "App Store" + # } + #} ) - pilot( - api_key_path: "fastlane/fastlane.json", + + upload_to_testflight( + api_key_path: "fastlane/app-store-connect-api-key.json", skip_submission: true, - changelog: options[:changelog] + skip_waiting_for_build_processing: true, + changelog: default_changelog, + localized_build_info: { + "default": { whats_new: default_changelog }, + "en-US": { whats_new: default_changelog }, + #"fi-FI": { whats_new: get_changelog("fi-FI") }, + #"sv-SE": { whats_new: get_changelog("sv-SE") } + } ) end end diff --git a/fastlane/Matchfile b/fastlane/Matchfile index 0bfe6495e..3e6b99287 100644 --- a/fastlane/Matchfile +++ b/fastlane/Matchfile @@ -4,7 +4,7 @@ storage_mode("git") type("development") # The default type, can be: appstore, adhoc, enterprise or development -# app_identifier(["tools.fastlane.app", "tools.fastlane.app2"]) +app_identifier(["fi.kansalliskirjasto.e-kirjasto"]) # username("user@fastlane.tools") # Your Apple Developer Portal username # For all available options run `fastlane match --help` diff --git a/fastlane/README.md b/fastlane/README.md index 71f7977a3..f878e06f4 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -15,37 +15,45 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do ## iOS +### ios print_testflight_build_number + +```sh +[bundle exec] fastlane ios print_testflight_build_number +``` + +Print the latest build number from Testflight + ### ios test ```sh [bundle exec] fastlane ios test ``` +Run tests - -### ios nodrm +### ios build_debug ```sh -[bundle exec] fastlane ios nodrm +[bundle exec] fastlane ios build_debug ``` +Run a debug build - -### ios beta +### ios build_release ```sh -[bundle exec] fastlane ios beta +[bundle exec] fastlane ios build_release ``` +Run a release build - -### ios appstore +### ios build_release_upload ```sh -[bundle exec] fastlane ios appstore +[bundle exec] fastlane ios build_release_upload ``` - +Run a release build and upload to TestFlight ---- diff --git a/ios-audiobooktoolkit b/ios-audiobooktoolkit index f05abbcac..90ce39a5e 160000 --- a/ios-audiobooktoolkit +++ b/ios-audiobooktoolkit @@ -1 +1 @@ -Subproject commit f05abbcac177a3cc669a3c6d9e5ab920629a9620 +Subproject commit 90ce39a5ea5e79a9d6e418e4a041f7aa114d4b6b diff --git a/metadata/en-US/changelog.txt b/metadata/en-US/changelog.txt new file mode 100644 index 000000000..7e5ec87a0 --- /dev/null +++ b/metadata/en-US/changelog.txt @@ -0,0 +1,2 @@ +- Bug fixes + diff --git a/metadata/fi-FI/changelog.txt b/metadata/fi-FI/changelog.txt new file mode 100644 index 000000000..5b36d18c5 --- /dev/null +++ b/metadata/fi-FI/changelog.txt @@ -0,0 +1,2 @@ +- Bugikorjauksia + diff --git a/metadata/sv-SE/changelog.txt b/metadata/sv-SE/changelog.txt new file mode 100644 index 000000000..d3ed4d35f --- /dev/null +++ b/metadata/sv-SE/changelog.txt @@ -0,0 +1,2 @@ +- Olika buggfixar + diff --git a/scripts/adobe-rmsdk-build.sh b/palace-scripts/adobe-rmsdk-build.sh similarity index 100% rename from scripts/adobe-rmsdk-build.sh rename to palace-scripts/adobe-rmsdk-build.sh diff --git a/scripts/archive-and-upload-adhoc.sh b/palace-scripts/archive-and-upload-adhoc.sh similarity index 100% rename from scripts/archive-and-upload-adhoc.sh rename to palace-scripts/archive-and-upload-adhoc.sh diff --git a/scripts/bootstrap-drm.sh b/palace-scripts/bootstrap-drm.sh similarity index 100% rename from scripts/bootstrap-drm.sh rename to palace-scripts/bootstrap-drm.sh diff --git a/palace-scripts/build-3rd-party-dependencies.sh b/palace-scripts/build-3rd-party-dependencies.sh new file mode 100755 index 000000000..5cdcc2534 --- /dev/null +++ b/palace-scripts/build-3rd-party-dependencies.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# SUMMARY +# This script integrates secrets, regenerates Readium headers, wipes +# the Carthage folder, and finally checks out and rebuilds all Carthage +# dependencies. +# +# USAGE +# Run this script from the root of ios-core repo: +# +# ./scripts/build-3rd-party-dependencies.sh [--no-private] +# +# PARAMETERS +# --no-private: skips integrating private secrets. +# +# NOTE +# This script is idempotent so it can be run safely over and over. + +set -eo pipefail + +fatal() +{ + echo "$0 error: $1" 1>&2 + exit 1 +} + +if [ "$BUILD_CONTEXT" == "" ]; then + echo "Building 3rd party dependencies..." +else + echo "Building 3rd party dependencies for [$BUILD_CONTEXT]..." +fi + +case $1 in + --no-private ) + ;; + *) + # update dependencies from Certificates repo + ./scripts/update-certificates.sh + ;; +esac + +(cd readium-sdk; sh MakeHeaders.sh Apple) || fatal "Error making Readium headers" + +# rebuild all Carthage dependencies from scratch +./scripts/build-carthage.sh $1 diff --git a/scripts/build-carthage-R2-integration.sh b/palace-scripts/build-carthage-R2-integration.sh similarity index 100% rename from scripts/build-carthage-R2-integration.sh rename to palace-scripts/build-carthage-R2-integration.sh diff --git a/palace-scripts/build-carthage.sh b/palace-scripts/build-carthage.sh new file mode 100755 index 000000000..0417210c9 --- /dev/null +++ b/palace-scripts/build-carthage.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# SUMMARY +# Sets up and build dependencies for the Palace and Palace-noDRM targets +# +# SYNOPSIS +# ./scripts/build-carthage.sh [--no-private ] +# +# PARAMETERS +# --no-private: skips building private repos. +# +# USAGE +# Make sure to run this script from a clean checkout and from the root +# of ios-core, e.g.: +# +# git checkout Cartfile +# git checkout Cartfile.resolved +# ./scripts/build-carthage.sh +# +# NOTES +# If working on R2 integration, use the `build-carthage-R2-integration.sh` +# script instead. + +set -eo pipefail + +if [ "$BUILD_CONTEXT" == "" ]; then + echo "Building Carthage..." +else + echo "Building Carthage for [$BUILD_CONTEXT]..." +fi + +# deep clean to avoid any caching issues +rm -rf ~/Library/Caches/org.carthage.CarthageKit +rm -rf Carthage + +# for DRM-enabled build only +if [ "$1" != "--no-private" ]; then + if [ "$BUILD_CONTEXT" == "ci" ]; then + CERTIFICATES_PATH_PREFIX="." + else + CERTIFICATES_PATH_PREFIX=".." + fi + + swift $CERTIFICATES_PATH_PREFIX/mobile-certificates/Certificates/Palace/iOS/AddLCP.swift + + ./ios-drm-audioengine/scripts/fetch-audioengine.sh +fi + +echo "Carthage build..." +carthage bootstrap --use-xcframeworks --platform ios + diff --git a/scripts/build-openssl-curl.sh b/palace-scripts/build-openssl-curl.sh similarity index 100% rename from scripts/build-openssl-curl.sh rename to palace-scripts/build-openssl-curl.sh diff --git a/scripts/build_curl.sh b/palace-scripts/build_curl.sh similarity index 100% rename from scripts/build_curl.sh rename to palace-scripts/build_curl.sh diff --git a/scripts/build_openssl.sh b/palace-scripts/build_openssl.sh similarity index 100% rename from scripts/build_openssl.sh rename to palace-scripts/build_openssl.sh diff --git a/scripts/create-release-notes.sh b/palace-scripts/create-release-notes.sh similarity index 100% rename from scripts/create-release-notes.sh rename to palace-scripts/create-release-notes.sh diff --git a/scripts/decode-install-secrets.sh b/palace-scripts/decode-install-secrets.sh similarity index 100% rename from scripts/decode-install-secrets.sh rename to palace-scripts/decode-install-secrets.sh diff --git a/scripts/firebase-upload-symbols.sh b/palace-scripts/firebase-upload-symbols.sh similarity index 100% rename from scripts/firebase-upload-symbols.sh rename to palace-scripts/firebase-upload-symbols.sh diff --git a/scripts/firebase-upload.sh b/palace-scripts/firebase-upload.sh similarity index 100% rename from scripts/firebase-upload.sh rename to palace-scripts/firebase-upload.sh diff --git a/palace-scripts/firebase/run b/palace-scripts/firebase/run new file mode 100755 index 000000000..cb0a97ade --- /dev/null +++ b/palace-scripts/firebase/run @@ -0,0 +1,76 @@ +#!/bin/sh + +# Copyright 2019 Google +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# run +# +# This script is meant to be run as a Run Script in the "Build Phases" section +# of your Xcode project. It sends debug symbols to symbolicate stacktraces, +# sends build events to track versions, and onboards apps for Crashlytics. +# +# This script calls upload-symbols twice: +# +# 1) First it calls upload-symbols synchronously in "validation" mode. If the +# script finds issues with the build environment, it will report errors to Xcode. +# In validation mode it exits before doing any time consuming work. +# +# 2) Then it calls upload-symbols in the background to actually send the build +# event and upload symbols. It does this in the background so that it doesn't +# slow down your builds. If an error happens here, you won't see it in Xcode. +# +# You can find the output for the background execution in Console.app, by +# searching for "upload-symbols". +# +# If you want verbose output, you can pass the --debug flag to this script +# + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# If the first argument is specified without a dash, treat it as the Fabric API +# Key and add it as an argument. +if [ -z "$1" ] || [[ $1 == -* ]]; then + API_KEY_ARG="" +else + API_KEY_ARG="-a $1"; shift +fi + +# Build up the arguments list, passing through any flags added after the +# API Key +ARGUMENTS="$API_KEY_ARG $@" +VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" +UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" + +# Quote the path to handle folders with special characters +COMMAND_PATH="\"$DIR/upload-symbols\" " + +# Ensure params are as expected, run in sync mode to validate, +# and cause a build error if validation fails +eval $COMMAND_PATH$VALIDATE_ARGUMENTS +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, convert and upload dSYMs in the background to prevent +# build delays +# +# Note: Validation is performed again at this step before upload +# +# Note: Output can still be found in Console.app, by searching for +# "upload-symbols" +# +eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/palace-scripts/firebase/upload-symbols b/palace-scripts/firebase/upload-symbols new file mode 100755 index 0000000000000000000000000000000000000000..1f019e008ee06cb7e4138c181a56d44668632930 GIT binary patch literal 285440 zcmeGFdwf*Y_5Y72gn=l;iPdS*nwnZsP*KoM1#y%Jfr(BO1r)0hZ=h5_3W=Z?0YjAI zaa!7nqE@A~Dy>>+z2OB6f&{$c9k1Y}a$>M5TEt74@AI|xnaL!eZy%4}@BRMk!{ZU= zoW0jxd+oK?UVH7e*WTy3uRhw=wV16o2z##q0zPmST(=0uA z2@@Q?G3Sq+FnR10(mLXMzu4j1Q;p)E-oKl^bEei#89(Vf2fiJ?f?XWGs$Yfxyu;?) zzjnAu9W&;_vwwBYn2BR+&!2SG#If7qt2*D|8{6NZ(0l&B_HQ|S=S(Qo`@*xtV{ zbokB+iPC%izxHoAe4?-R;>p|77ro8lyQ-VRqWAoN?cap&oC_ySZ4;P|^etTM@HK@< z^q$YZeB62-Gv>T=&KWay`Z;4K*N&+@>+FvB&iseN*LOEpQtusU%EvioOx<_(@4S@` z-%(+q?0Y_r{O2)a#!nh|;h4!2#=Ay$r0>}f-$Nl$djGC}&^Kw?_(|s)S^zuZo7?Q@ zn_TR$=>5AeN)OCsu#6cqq+(=6Ud@bm8?m2+Y2o-U2;Zd#Gz51Kv&W2?G-1rtizl9a z;e;`hYo~lGzS0oB0DR#PwiJ!m+1WgP>DLR}q-1;gN<;dJomwf-dq;c??eI-F>$~Xd z@w{uVbfW(0Js+Ri`xnb`|7|bF?fF;!vcuOu=HT_7k1r3EJ%VpszTkE2kI^4Gd>cZ+ z)BAVhGreMZK(f~nU;o}k*1v;7{^`8~zFb#{z)(+3nsCm9sXM|q{Q!qA6uSbwe-C`; zoK@>aMo0Q)b-<_h?}2aflnZMw+!1|qLwuS$^-u2|@VSie|FFH|C!TfQSR26|#>d(Y z^y&S(##x9jr~Ep$cU_2Y@;FC;-oFQZQ^!u2GIku(Wk-C;-?{$SitV6(de6tlbho4a zHU0@>M|^`8I(*qede6t_YH9mF+g{B>JHj_S#5X8pn%+C$%T{GbLwr-~n8tU6Z{D9B zeN7<=djB5y#$R-ntb*Z9CUUuB#+*I1%}U#z zfAf|&d>irxMgBbA5nr2Ko2okgxXK|_Bg3ki9G-%OZSVGUqkETL&d0S6=5k+UQEoUw zKKzNIf<-$!SpC2CxuSx(^ueq*iwXoM@_O*s|DB?OXZgKrb5X%UBv0ndaQ^g9__Ke4 ze_Dy(@~_9giwb(?6BNQ}7?$&=?mwh%>Xbt!j6eI3b1$B7F7NvHWBx?P>9=lt<*=)c z9C6pZrw&~3x9a`(B@J>43U;OuyX;(WK=xf}{Od(iRBo>q>^1kF>QVcYCz`u;axKW! zP5qY~-0xsW7=JeTfe8|u#7?sm5oN~d` zLxx^hHwhsff8nHq$7NFwIeF}qsiaIjWN==7h`)b3{O|Kt*v1RU(2R9(MUEu$9bNh5 zBCFp=jM|rTBp!TBeo3`wG=JIljNAE2+S8}tJK9q*dGc}NYj@lhmlx7=ejZ-Or)$3p z@8AokjQwt2RUFbDW{36M#&D$F-`*d>F=FhLi^iWbcIu8=;cCf3P>25Q$DibDG2`KU zINLjX@4AhN!d8Nv0PI~L@;fbW5cr6Wee*A^YiV6Tb2Qadd zUURVQKZTT7LEbX*D3bEN3bSq{tIAtRS|(OOiR#Ap>t=v!zQc7b@FC>IK&HHjYpXo! ziZ`kf@8dA9CRagS#|n;d6+qCtOGUTHrC`dRxRxhX*PYi)>}hgEh+peaqiGqHMyF6H+*&Cq31-j<5Y z%TWHFfi&yISn`Iw!;*JNqP9$I03{%_L$&|;tgYG+$%aimlIhBINw0s>FIo5-)tW4( zk&O;JwFL)2r>batqjm%w9RY<@e>wor`^2N_omc4{BkWbM?D<;(9N8`Db?%ml-3LI@ zkCZ5}xwBbt)=7UMy~$Xg+ z#?Y*Ul7UwKi=_9qqbHb0Lmg|@I_RYLdYDy57L`*fW~DY-I$io|%KM@Nzn<9K#xI1o z%G+ig^Zp~EzZp(kV%Rg8*h3^G8=Gp6AaSA+{hqgz1j>rcOOoGhpmG$QOg61H`6UaX zy&A~YU6ScU0}JzhO~G>3T?mfkMbeV#c>w@fj*J*CGW__Dtd_(evci_#n5*Kc8DbIq zaE%Vdz~S0E4_9tTR(b!0!QIK)Zd9(SZp=jI$UvgfzZqggea*w_+Oo5GSF?9QqjZ7z z)~-Cf^^yrcy^)Fi2{?FhgMPe^!Ein$#FF&zLf%xKbP|;7y`AzlTW0LF91gwvi55?N zA3q{2?Z^9D$xPCF9Dq4ZwJ~xJa@gQ(Cf17@Tl1>OVpSWDTsK5q zo3`Qpf_XM}lis@aB9Yn9)(>#(myWC%!sRFKqh#0@(Of-uSUtJEXbwLA#01cK{`amf zSBGhalgL#SjGJdn-aB`#vC)t$N<69r@0FUC6>UI^+XMNLTMTITwo+G+&~Hmk%Wrap z;y;F_elH+cov1(CASVn67yWhBT(P_C>x)$(s%Y~PN&FMEaV<~MXSt!)6SPjSUk2Jq zUCL{L4{ns*V+H796ongQ8s~Y+u>Dv!t>isb<$XhCGbn2UDO|3&#$CF8b;{cx4t*x} zd&4xXtz~f>%=p;Rg1R~Zp?UgBwIW_=bZt(0uT^_nGqGI^X>%|EV46DZs-l8p{Ud*N ztk?NxnOGs2$2J`Kvx3@Ptb@LM&{Voq)%z&ocX?%GnwDi`zic$2aW~K;R99BNTa%oE z^}dGA-KYb#SOhUm(3y!{1s<9aB)z@KKB%o3e^oQ?`!~%H!m#HXHkEFU?ppcD=IH6G zd8pnR{PCm0g3ZxWE4OZrj;<6xOG8lRcQ9;@mPXcJ+eyDA`lY9PP-C{Ijj}55*`$a| z{QU~!($SQI<)1uYGOYSGKyE)$9pjay0;rb*s5C;jTRnOJ{Hh{Uy&K9Xmrc_CrcTB?qHI^Vbv(eJouuP2R_$>>4LlMjXF z)2w8_<(o;_JT7|h+GKR_r~NWP*(S*o1`3MltDv=2)&rd{b>aFvPmJ3%gBwWIl32Cp z8wS!p@3;13UStsU%kjnYt@TYvbdM~$m$6)oX$W=Y5~w&{ zRQU1r_lb1s!&Jj+is)S?2KHiN#2gcygMdWuS3alNE9HHe^2b8;hS0F;EGDK)_Qv_2 z^mhVr#F~e?uUu^E`xVl@tW#xBB>tMg_Y54uqF8q?#nLyOpUI%>yTP9&^w;A_Z*VbI zZ8!V~JeKk}*+%u?9w~1|IpRUfj)G8zsBw8lucTi|%Ln&QdFKpD`t?gJ=ZTbeL0@Y3 zRlE536-ojDYNgU}!Wb$tBzj-a_V-9v!{cXDz?kw9rcvFouwrt9co6Z}GD-TSfD98z z^YZ^fcxAt)Ozb)}gc;~RA6hr}+tTj^(dm6!kr`DA`b@0RAl6g=jIe&ceu2pF>*u+j z#r!x4q^Ob_R!;Arb=oXS26&Z+()}7<9BQbgv8nmq!S2Chd34jY;n_GgDMS;yy}A|NAp~X@EM1f69D z0xo56xTx1s1I6(~*k@j4Q+6O%E`|ilWaQPCi>ZFeIc&_O(o09vcU4|g8shOP?}TDa zbLq&xc&+k=(Z`Xgvn2)yRytCS&LOo2a>ke+R$lF0*voa2=1p%RBdWfs%A46&HF%Yb zk7=0Qm8HNY`R&2)@Ej#o-k3p-R9j9kX8m~AsgltT5twT4KS{r4ah12O+WRsSJ4(bN zZ~TPg)So#>!_}YJ-~CXh-o!peuKkbnz{>iy?uXIvN^}17FM-oOY`SN685ddwnpx$(E zkSfVwY)&1t1Ic*tUptVDk%lW@GORf>)NC*h`c^qvL__B_@s0u6HM^hPm~b}{w~qGyRV5}Wr1nCDz8%7EvI$ zSu(W|>Si(1z>Xjj`xpYM{Ccv>KIf4si^gSMY}wOvEzRGidC7YXRa}udxwP8*rpkLu zmABv#lnOj!4QxwSquUFsyysAjHCj(IpQtjw&u>AB`jIO9kWK|nDm}KT+WYywwEl&= ztpgYg#gy3BN?5bP5=$rnzpK2{_XQx)&0+2gTm|}Ho%*h-4xz6y{45ar96+TuIIz{s zZu1k5X_cFftdl3g6!x_jlF+>TE92*eOzZ>E0+mBtou;rI|7g9Mo<+!rVtG1tF8+Xd zaBUgo#AKHJc@6-kdB1*^{*T05Ba;Iw*Vg@jVJB(K8+JkDz3dWTSb5Svg&sVC;Wmuk zJ3*cH6Vd54W77=*QO>4oKg=q~Y8z(Xp>i*IcLxLO>$^;XzEkCn9D#*H2g|_G65%<@ z*ieYqPbw;4%9CJuuVW5Wd!J@v3oLuR+UeGz*O6evqwAUfCrUWtQ^Ja2`!jIC;Y)ze zX*T{h#ozOnVd1RR8~KMxLf%?wAqiUbEC`vIn-{gfsPvvT^9)y1pC1`v%nvpr%FvMk zw6=22`_Vbtgi%+i?!Q7eef}`{*5?wK-Hh@|WLj&OLs)+T zI9CmnR0!fzm@dKh`}|Ib{rc6a6~E2|VAHWntqKihDf0q%m!5 z$Z2&qK=Tc^bE<{X?h3SAqt^I6w@`^Ss>~X-0xG`#n~|ULKCsp|2g3~sBPad|St0ZN z#5t@RRj(uSBmWAss ze#fuG9$T+AHbv(&nh0zR4g~CSKmZVWotXx*i|^{~0Jr`Kgq=Ys4@+X8 z!~7dCLsK>Rba77M(Bd6>Ei@Cqm`ul?!~&&DgA-M6y5w28=e$Cwj?VcJPC6i72q6w} z5EJILLHq|b3&iswM2UkqCJ*982k}Y>(JCU-B|Y*WuvCQO%@AUZgE&5qj^DP&afgHW zc^2k}OTqtQW_|1oUKaSmc#2yu>sD9FRn+d(`XLR2`256lzl_|ertJRCyo?I51c zgJ5z{TkZ)V{`;1-_MdqWD;&ffA;cRFVnH6npB%*XA;d!t;<7x5nGWK2A;fhK;@mul z8V4~ags5{6$L2u{bP!WRh!GB=Zyv-R4q{>m(a%BrFc0DjNqagzCWMGOh;Pzu^6|2R zI4Okq=uP9tyLk}zI*1cOh^HLH>O6?wIf%g_#9tl6-*XVPQ=wsCnCrXT1#P*b$o+Yk zJJID{-j;hfxrc_iC%D`RZMl1pTNdW_bGavnxmu>QnYE^jSaO^X&pwOp+IWz&AP3wg zea?8QT$@bazhoO`Wixxd;##8Ta(p3=zg}1nJ*9~y?PM~ey$AQ@ubjWqXzwD_Lnd~G zp@`2s52mKm!@*mzM7yF%ud%->kqUV|6B{Nlud!T78oE!Ks5S~~(jQc6L^N)&x5!g} z38`u<2K+OeID0g9GO`EpF8i}F$pe$ar$90xd}Re9MWVrL?4dgFM~<_%wGQXU?roiW zYjJO%xVQJ*+gA7XmU}AzOJzS0HO{j1v=KL;xVC%JU#gY`m%M?n_>I%a#v`{i=`EER zob>M(0k&>x4juqTQ>WJB_Zunc*j;R5Wn#Y&&1m9lgvD0uwCATJ+T5Dh$oh#QMz42M zlSt5{#A2*DILjf$p%tBTpay}TXcBmHV<|PO`}(cHqM^7Nh|ejNPAexYz7NGy-g~xI zTdMR-Z27I$JF5X_e<(U<88~DR`S&}f%vVP^W8i%x0wxDW5o_}M#i-1S^ioyOl(BR!qf}+**|KS^*bXGC1SmW8$0$oh|%0YKFtlGJJ zpLDaO49li`0H(j{P@cbQtia=pP%zo76+R`%3RTwNw>|&)pc(cPIcuf zxvdS_k1ymUx@>L81V6r@EfZ9IL1pgH_*_djbJ3bH%ihCgfExSk?pw5sw$&gso!1W0 z##amxnPeSFmJy_W9=1KAbK4<0xE-RK^AUYUKjaYYvOS_7w;^I=Q`u&9T&`12GF*6r z(O2<1@^QUjaBZzaI-Oo{ySI5RXt!tON6LRKwVPX*`H{m(K-uJ_^t6;++frgbCZ*q+ znwHrwXIH`{#U$0Vtjs0EGA#N9QB zjL1+D=H~YE{MaiOx`v;dD-(MvOggbGsVPi4sx9gMFzLWtQe-np?Rw`OC3tPMMb>qM zXl@6gHH9{jPE~5*dUiJU2RjLaatS|l3H#>~A}(QR%mw=meS?@b=-%42K?T^d~T#Li^fGQa2FC}Vm?d)Z|U-4<8m5Q@lI z!ajf%die#zX^KZ1O<9jgOMfzQbSai5w^fQ~n@zJsHI=wQEKO^hty*c@Zs{SKFSRUo zp0z)p#x`TMt4YBfheFntiN-n{e8G6jSY zteFF4#~Y&gE*RXAOuq4}YN*pMn*kOX8E=bgFFh}5i0?1<$mQZSo0GLUctja+JDvD3 zJN3?Mdh1RyjG3~NBE;`g0YZ3?^8Otbx`INs)e%3~vanHbJK)i74lb}POi6(|TWqu? zDLAOupmE>{vLaXWayHD>Tg0ur9_;5TrvXo1AF6oNsp&+S3XU)EpIPLCpn0t|Yl(zN z5js~=B$cjj0)HmzN z1pr}PpdZ;t2z{G{VXnaq!klbaRi12UF0W}h2{bN6Z^wpjCQJ&+VHX?k;GApAuE?(PEty+*bmu{^iE*rEo0EFSl}R*whOy{Qj5pmfvT_b)x=jhMsx?fm;ha z!oQY=91aLcVa9`GXq_R4V9k=Y0=HPYEY@K{nKM4Gv~*S#@iB%6R=34wYPWk!|NI zgy^?)^h22ZVv^fI{t6grz;xuPMcH2bHBhcwNPZt(;Rra}C7aQyeO7kq;@hmlZCzLe z70%47FhJXLrE&d2>WGhMhrrCeW%KjQz53NzK4zKAKlA1Iw^>}X!|r?Fc?@HVYGd(%4DM6A>y(cZS!i}p@y zsTb`%f4KeJbf*2>HramI$Ld`-FWS3)VKUuVKvK#}vZXnwoG`&2NpE;*(wodCOv%t| z#LbFgL3lYR2z#DNm+_ zP5fCWNi59GVbdaxd4=nZGkD|+%RbRh%Sb=|IFPAy^M z{9@Jr5p$NZYw$e<=!P*SKz|r6=ET$h6QIw)kS{=|F$lL4pq_839-HW4&LS`&Kvh77 zlj`mW1L#OR(u%{T+}7et1k={-L9t)EVmkw&I3O&vX;wFTjh9(7A|L-ot@(Dgu3!0o z#MW^}$oCqTgU>Lw9(jV;x=iJat$*YxpRJu4x7)EbafQK$!NGTtUg`IH7?=3B z!NM}hEj6UypGto>j~-#~rM=npzog%fF+#ofi2_7v25*}^58y+dfz5|c$xca+!blu~KYeV8e+>n_%T=9w9d1|Q&rHjSZ z&AhWKl0j_-Ujbax`nq_E8R94YrbU_`KdxFoW%p5)%$@jPy|b?2IdO`Ldy(P7AN#Wr zlNhWt;ya++G>QQp>=J*JP0a3M?jX)D+t1oZr#jH#y7Z zHfPz~?JS%7on=!$i$EB5NFu)Pc!Q-)my|$U%6ra~VC6iF9&J#h(i1Uh6m+8)E#h#N z$eeK|O{E%r0!sl*n`DX~ThBOaWsy*8Wy6-bT#==W30R`NgD^N+aVftC%1UWF|G$WY z^&o~QVLI)tY(IT6h3XqK?z84s5#kpWBte|9YILH@O4Bp@x7Jh}PoI-I-mB z|Na~8snF!FIS&CU*D!?I6r$G!8C4CLPPI|~FRI&*yl&*RcI9E8EYNa*V9pDF zV?@O6;srKjVt1;j!fZDN-Bq=p7;o!`Et%MK6@a8yXus>X{TxZ`|C5EJ*Ta&XkCia6 zsE8#El{zsKOQ|gLGz%ACZU#o7+2^v-neta*?Yu9`vpXO~TUgbr3G+%>%yeg!qt3If z&gS6wT-}>hk5IoeS0KwaEWZ={|lT0z_Q)a4HqXPWSE^50 zZEB&rH+4*+OG7u?z$6Q}50*IwFvt$0drpB1j12a9Dai8a7Ol&3N2X>gQH-BuXq)9{ z)4uF@UTr+dC1@@N?a7p89SotjJ^mHQ87l_@-EOQ5cVYF1RcRc=yBjhTlLcCz8`76f ztXz~G%Bd|jlrynUudp6}L8}cvekw??`h)>kURvw63H z%WZVr3131yAJ9GY7~xj6lL!P{Th-ioUsQr>tIQ!m8Di&Cyn>K3|Hyqav9ow_evnM8 zI)`@zcq`{@sXc=8KO{=FuW$XPV3>&BW$?j2ev}C(|WH~O5B)Owgi__NV=o(jp&@ajfasc;afAedl793Pr;A3)iHKafK)2O@o~2JsT2bJj>J`A@6V%?HcD zbih!O)3Ki!H%v~=m%S4NF*bw=pn7_T`A^fDCQ3;%ae<%)r0p!=OcHWu0oxs@vFXi4 zVB|gK{2R!)qF?t`EqqItc)((w<{i+Y%aPmEaAsr z872nX^d*AVH*_i(Vh4UY?sj#gWIhF<r{Do1rJtZr{62!f= zr)1Q(Qxe9{$M>N`Cbk!VOdt`(PHJ7UyAc+Ts8%;k;_r62cN{VeYl-vZ)L~i64 zob^PtTLc5^#hwq7Os9f-HIl$$(o|F?Golpvy4%W_u=w%Cmd{ZO2ZHwaA2ye(Je+yz z*r8UES#&J;%qv$m*s4{p<#rFQ#TV%K3o*M<1U*CH-dP%4%%M(P;LPKNkcjvuq&XAY zGFwe+4n~F;{P>$r$}_PyEDPD`aCFU`KnNXj@wW`kJ;1{3-NE}(w)~BxEiP>B)UPS} zK$B^LFmSbDQ(yZ1^I6oKuI40e;Sz=|r&}r%@7+g3*sH+wjQsgZ(N=-m?c#C}HwbY$ z_R_7gE{+m$4J-R*V__9ETyiSobXDi#!ffJYCe<_Ec@!HnDjqVk!nxH ze}@Or%fyB6s(*O<`e#!~CU#i6`Z;?Mo}z(@^8sKS z>Sl!h*zjOjZ^Ql*=?tTi z2eJbZyH{!0KfRe34d|*6D7Zfhq%k}KqY4dMuS`FF?J**b@m|9_$|Y;-WO|-Xf@5WD zHVy(s0h|INmsB!|q?(o+atV=9B((FZ4^e{7(as2gvM%)lm0`QsXNj<)vVBO%cd8#7 z7U-zzk3C8l*@s$FZ*~c4{|=sVGl~pEKXH&OdO!Z33N=he^~I-u-DfO-i;Y%-)sohW z>kP=P+T;K?MQw3G?F@;QeJGymn{Zb+DP1jU27*z_kZs14cQ~5nUDkD>ZF)-r+w@pU zV@6eb8!bvrp>EWD-_eqlKL5H@rEA<$inUwWUM$TqzxF2JX>VldW%8v%i+XkoGbpo8EDN^G(OLajCvAepyx&Gv$X=`))x z6ZdM_%(?U<#m~fiP`J+BjW*Hu*(LdkDt~A>t$SL%;~%L7_?L7+HoM*N{WC%01l>mJ zskv8EBgcfVZD)@Y7YZrcL`TDF1R-#Xl-I;u7YpzUs0%9oNgw4MIrbxmIAXfiv?R!L zRYvv<6QOV;#h65zF3HmkCV#UxX-!YR^dT!73#%ZJ$mb^i9D{Dm)b5gr-9$c;-NFU~ zaEUD}PQd#y0tCO$CsSSGSu`Sr@3H0ZP4e!9N2x#3pi9SAF^w5yb8!7X!r;a32WG*{H*8Ol?vK!x#e>VB1JE?MgKv9mdaQqiK5q%DAXE3VZ(M z2z0|6#H+fX*R*nzVK}Rh26rxor@jm9^p9LekOA$Q$6kI&Z7cZ}ny^&9Dwa_kzBI`~ z0x#BY|wdp$QF<)azdjD>{e>zx_q>^mhq=v4%(qpKsNg)X3KJ!94!{J2YwNTk+Ph0d z^H2qQD@#$%n}gHt60$@u+2?-zr{H`@_ng{7$~LM00wb*_;+qa{V^#BU=}V6;3|_oj znV9Nd1e0@c@4J3C8~wv1*LNIsLb~(OY)#Z2((eUay}RT5jXuzw+4#BS@{c=Twb$Vl zb59>t(C|+5s_y+N=B7p!CNqy$4S2PV*pd%Zg^#Zi8xpe5q42kc{KHJ_cJ}BcZ=J1P z7N{QwU(gn7{0++UBi-!BiOLVrt7xG7z44(CAAE6V2RR|=Uh-rbHnOHph^R-g5@p9( zm9{!rX*^vjJpfyW_0@mn`mdD#x>ENT)D2Tf7jszup#Qfj1_os&_PVMGRgu&~fyPot z^yu-ul_J#qs{nx56eu!9ygcS@kO*6@K0a zpzBfqgx4kCr1IwaLeZF9kK9-G6iq!STU`Fj7hQz5xyLV`KJfu4k$13f{~< z$W8zTmEWa*qov^lK$mW4*QImSPA}}zcL205WjV|$d%lDt^P)NvfAb_D=e$ujsw%TG zHSjj|+Z4ZJpPdxnzR&iv8geab9B6%J>Y8{kGW)&JD*c>^?e1vF_GIjvDb}qlp5QEPXgGYT6>BcGC2McLr&P1IKcz4_a)g&Kw>p+{v4MZ&Z0_l=4^1 z5#A>(l28>Ru*wo*>6oShhi4;l4){LNCQ?+>rvq!6+CzcuI)ECi8p(t$TZ)}y@jp+ z7WFdEG=~HS8NE$%FxIiyY!3cGDHL)S2v~=|fH1@LL3eeWG^1Ov?eNDzjxKIR zWaAgg``X<6HPFFDpvj^%F^DVII=RlTs}Yh{Co*Q#c(;Yg%aUcFPs^)mW||hgVP5 z6#4|iJ=(jnslxA)cyimr%WAtOmOZ@f$+}^c{K8>2{4|!;0N2GR>6(HcolAwM;>m)!yOm0**|u4-^4w z_Jp~GGO=$iME={ILp2K^1ukhFzHnlCm#kyskS4N-ii1nVy6v~UO5rJL+CY|Dy7T z)l_^76trZ#A=WygP{SlM3M~>F1>=Ocd7^}PrFP&>)!xC#s)nNqYL7?i*5c856NQVY z1$S}Esme*sVSeSC4CI5Ty`aGF=bzY_nY1FK*_#bDKiN4cQK(*9yK{PQ;lP?Vy%kel z(_9-HMNM$O!zPfo)k(`$!@BJoy8oQulylXEh_tcW>~7=3=?FoAL>8ZAiC-C16?I`9 z?VOb$FE{p^&SKy{rSUES1jlKi(2tNtVU_K%==O@X4C_`%fA~iSWscpo{kVf^PsjPHtQ>VrrnVRA@*=r;(=qo`Ep-vds(}qV z!}q3C;f5-&t9r2~z*P?T6#H?&Iv59V*Hn>iuh?$~`XZSgR_yvh!>2Ipmxh_81=0CU zVa5r?(FdN0KJfhVmeS<%4duz5R%bK1?>Ix;=9U@VKcnTl*Hzl$XunIt);(%}+OV~- zjy*=rU&oWL8*944{-He_`&)PGkY`!D3ROs4R-TDB_!X8Ef#&|Km8SQOmN=&T*vkWo3jF90e^}=sK27!Ge>u=7D1!pU=wm(ZW9XWLSynMY zw4W_xR?f6+;zwAr?X~^f@Y1<1R_0YmbM3PS9izZEv_IDL?OJ*}*U4!I;5z9NHi|Jp zcKnWmWr_A&G~OB#F4KrdCz*!X5}%E{918q<6EXh}b*8FBqQCu~to&Po$Ck`Au zx_6R}b$6faXYOqSJR~7-GDYG%k;aV&Fv#Kyq1Z*Jlue>As}`TSw8*d!b?w9CA6Llr zrQI=`RmDddIr0oVd5|b{zUN&;4D-%}ux=5!v(o6m{?({`TJ+(0>K(y{{)3})gpM&( zp<~us_lyIEq`V!$OwR{M7G0rF{hr*bdFmE~ulaq9eq%+Cr!0O_FLiPJ9Du|rKfc`c zWR|B|?Z(GK2?T_!yy<53Cg)}R_(;oO#f^^{KI%A2RXf;U18bZ2+Wp$k8YECRG`k4Y zdP3Ly7zSMgvT>Z)rrJzw`Cl7oio~#_4LeYPxwZ{&6W-Mtqhk3j;6ojwG14B)_Tv}1 z3XJEF(i}W>lc>~n9X=2gYRg(omPFT245yUMm-6ZyC*xfB zxig4pU?%qESk-LTLA}BwO>YZ#IM5M6yB5-b*yyaOz^nQ0ou(lkD`_-^j(- zaCf?(w;ky(CkL#k?abP5Bn$X`j3_DeP|i<*E;-Zi#pKckTblI8j}4q*fuHhavA@sr z=NeOZwN6lIW+wJ1iP2>%+7s@aXc&Qh{4Ru<4sQfZA_O}&-00ZB{g_Uxk?s@#>tCzl zlbj)fMSCwU3hnxwMKL$TN*0n-)AE;GLgYHRF>)(Tj=tO1MD)a)8 zQB*dPg#1P4$ShV(6KU?-v>1%rwdUr=WEwPLUp+PlU*AA^Op#tV^Y<3k=EpH9VCC*W zmBfqyd;CH6G5_Yy`8~DMap5^qMNL{?B|bY89K;c$4eTbE5z3>Uf2ba>nblmTrlp)0 zF+mpte?_5XRw(iyUXLojd#7rDNGEEKT*rGg?Z8PZIIz*sv=!YgS}_ zzUN^6GO>+kQ&;|uKzyvhcRxJY++?j9@cgurWKrtyVr-HD&quEfZ5jwJg5XT-HZb&C zLtCQPEcZgY1~&Y}&~%O_{gKhoK7zbrr4oph^io~hQoj<9+d9#Yv>4O#&ZjQv2ysV8 zh?_e?q&q^)=?F2kJp`)@f=W2Ftj;)Of7|z1eOAYPkA_YCE4*j9KcNyO&WKzFgiX7N ztNW=H@&7U~IsZno`tYL#^r2s}^-NyVH4C}i((V~dddC%;T8#XWDOZ*?qpU#)(vj0O zNqg>&%OP{8_SKN~6DNbv87oc?nqt?5m+||k(7YAs7ovh`Kqavh>oT!!6iNB#aGEC* zjDZdn@%u!S>Y_DmKa9bgv4M?0jc3JaeCwRc!n8j(>JeLr!qwG_i_t`ns%`DBUNqtq z{KHW%^y;EyL;dQ4Xya9G3+UFqQVeyAtJx1D5axKy&-inU3KWiofQ>MO$p3Y2X7Cfw zV@Fo`$Cm?m`%lHB*e&e!rP3u!_>rw#*(6i2ehH_`5cwZ~z`08&fr8xC44D7O7WLz+ zen$70hxH`OlbQNUD%ZsyntLWL#M_OeK0Ah1`PJA+Ph{54t;B$3Hd{kt#jMNv7DVUF zQos3$TO8KOV1<3vniiUat=EQx$BV&iy8_|lMdllp*=$#*X+C&M1JfV1n)7;@*l1Ot z9f9{?>}kAM=U_ZCuhFS*680v}aYu;S%vE%&XVt%2Q2Ucv^-TqJJ*xc6BoH?`j7yA} zU925tQNyK!u73SO3@keYSN7!@YGnPQoW;df$-4Fe5MIA&%X)2~qS2qClr*|O1JN># zod<+nV?Z~58&LKe0mu>y9ISELrE|@76v&EpIGt-;<<2$tL~25V{K=nSkk`#u*V?7^ zqofZtcnayjZNcv>N9UUVK_XLQaIsR-iG$f`;OzQOudy-tM;ou%TkQW`BPphjKjML* znLYaa3a|Mi1Q;79-)0GAFK)lNTtc3>lHv?oNyWRW)|N$^_f}KDBWvcr`-n#8%x<>_ zd^$zjSpjgYmnj}b@p&@F{X~CiLEwLCG;?KR9b&Z2iT6~ij>~tsZ_nyepgv@r=F)Wr z@^A2wB$qzer8kkjIY0eC(#=+oN5g^kuq2rZqrnV!NcQ93FfyadAOJ1&u4y3${ox;M zG$1%voo>8D_?$I~|3ju_ll!sjN&Wi8_7?v)*uczS3?l#_eIb|}2iHjpXt;jDMZHX; zG3tNXmB6;j#7e2DbuSVhbBPY;0Z^-RIOsdASQzD7PgAespO@-dl`?>$%bowS<-D>>sk7Hj1w=GuDS0%~nnp{4J#0 zXtx6QsDNMc@Gqg#LLb^@4{S=gMVLr1R!T;j$#7f`-HR;y&_nC{iFYM~@*(X3iMc*B z27L@lAhznqgwHBP9@RAx%fFjsX{Giq_Z*1;hC5lIB5PQgY}@K>zjKO#g1i$pZ4nhW ztEg(g(qn;fLAhhUhPGce-l~@typVS1qWhNoF5Azg#wJFJ7C7)aY1s5mna@o4ByFJj z2|4OUCsXnD*}Shzw^;!#r>09mUQXvASk~*?Ef(^0*=M0Hd;Qe!q44hhHlRHD8Lc&| zUv?FsG9C!8T#4!$A!FE&uM|~&VwB-Ajj?#1$%}^M344iTrzM($>s*G$@U=e<1<6WW z<}$Qy9MvvktTOzP$)oA-^u)PUUNr*YZrQf;F6qc`ktTNpCUOKO0*|cxxp3C@`)mrW zZ!(HW6%!kci6{j^JUPLVxLc?lg|@DdEHR{Ct@i7fCN>6d{nk3wfpFVwx#TQVf==jc z{Egm`SmArs0YD~)@+aY4^i z1O5VoaNO7|x#1M@hHm3i^*&k_H z6$emcjVtmvMcnZr8Xdx>3>GnrU+NGxg3$K37^rR6yY~bPMM*zD0YOd)WK~A|g*`+O zZE(xluu~(uh3(NHpeR;Fo@!kYbh$dasEcX6sde7P>1r zmYlbPjmdQk8Jxra|2=5`)<{Xg_c~lCow7-x&Ct7SvF6z zirosl$jcpXdQ58w+~4r>=P(OdLRAKZMx@!?$5Z)-uJXfn6VH485gg{uLevD!Go^>3 zdWa<($QhG?nb=%l`0&cW?1xuoS-oxNpLn$iLZ?Pl-j<{7-R1CPGpj111H01j48#$i zSWdzAP3vn@ZDManVxTtoJ-<9LOJXpRo?=2ALkfIFb+t3Cs*THLTGg1zaU8waoQbUk z+!nVMSbe#1<_lAMIR9ppXJU5%fZ~MZeY3Mi%h)`=Yk9zg#UR6jcDX8dOPC*qGuTGP zvUTL~%S{r&ji=CEuiYOgwLA1a_shMS_j%9UYsC7q&Baob_`7v5 zezKa7I+jZ}kfviv$L164)@fe{=dIT<*}8Sy@loZSTnz6A?rLN0FT>Rex=Uu`-bOzX zpaVd#3}SmYVq4C*GEe;4VwhjW*S6aE+D=kuIbYkxQav^Yzon34QFP80b&4PPh9SMs_Q%DkSj0`aKROfW(Bf90{?o{M!?wQDj^*Tvedwm|EE*KOb@|kaD*udfM&VjG3#wq!dtAE8NIb?H zIk4E}#UBmxE^v8=k#`sZ=1d>lyIZ^0p27b=u4@&Boq!V0?hAjrU*S5)kDrS;AP1S) zAC8Ab=B)e4Q$6~xzcKDpN+xdca32OIki$r8I36W z1ej{Rp)p(I!^YC=_-ngF4Shf%(+Bx}i`~N7zteB=LA4{XBM^p!Usk2%NKxVv7Jk7A zj0d{)3TU9!kZ0o(U33i?+?b4v2T+Qtre*ycC;Uj{>AA!wbBQH~SYqdBzPGewpY0N} z=1dRem^1rkaA2-vSgz%pD_4f7^UalF+;0`$=ZHAo#&{%bC}*qvqpeda7gk<1ja_2h zC$>KDD+@RQH}=sXbL%vagP(!XtyhlIS_FS}iDZgH&9|mZDKa6vLk>K-9G(#8L$V5f z*pTh7Db`OowmjS;Ys!$f5hnk+=7|d(FTrn6M5@60hdzEfrgF| zwU6MbX_nQ*_c&O^1{3)dvl1`JR-f?A;0OO^q40E~@e|2xI<_l&o$~)Z$5t5Un->u0 zYalhVxHoq?Zt#>hb`ccr>e~0XEA{n-LQ^>xRNQk!fs|K2PgQQcJj<$2SddUnOE)oO zhT&`uUbAd1XJ<=;%3lIeHDT@}W{vSg zy{qyftFkyOGA^t#tn1Tb9m7t@)peoUk*BVg;X3UPA^Nzw;7wj7=}Ih<;n)U!igywJ zO8P-5%0U{BD{L0xO&q~hA6*nm>HULB{>MAK#B{)23=SNYsb7Pgm zPzeSZK%Cnl9Xhs63Y)}bc8>$3WnpZMpwlIPZmYx}wV3-ZT=H@G$x!Dj*-z{a`SQ{- zdEA8Wm-2nI0Tmsxn$|o>HEK=#*_}nsXceJB4@iMa2udDsbO3R>2-DCx%z$Xr5mo`R z{*W&8r`XI~v0HM*dS;7#lN4@>6{%P{_D4W8Qb7F<-N^Yz185Eg(UgX z>z;bJCyN@B>ij`Hy=Q(+IYDq}GCJ`~>1D3_ndN>KSeAKp?CW2GSmd%6>L*>_KWI^t zP}xB@6q+05J_gh5l~U(<%Q1AQyM=aK%Oy!0FKgVHB#_0_j5GaIQV;5q>MfGeSkThYFcr{mPPc?m4`p_VB_sZ zK-JRNRVst9<_!3jW8qxZPGKL)X}I?&$bAO}+#K8q2%1STYKI`&zi}`bU`!?LC$NVQ zK>eGU9I%>?4W-Mct_y&Mbz;yEt zO3GQanb_Sbo>)Vt)b5^5yWY}PlU9ePYH%+;QBaHyC^Sm1R%XM>d3pecM?DZ?DPTdUpdhp--GntmFmF^ENXHH(5 zOtW#C=4(xutd}djVZ~@&^1}d9Tw9YRZ7Qzj<6c#Mb!j!$PL*GSNj!4j@@hXt)Dur6 z@3n80KV;uxg06)dPyQ(LzCjcL{l&Uf~@ne z9o(s)kovZGs$M8v#4VISZq&2i=z(?E*)2)8y5W;e0z-Cp*?69 zDdlallXJSaM|kj#5Q3-F;Q{4f0+5FG=!nP+W!4c@Y3(6S?PXE1!7; z5HY&WPxeTkSm+J!F=W7}^#?sBxd<+~7kWtm# z)hOqlShOspn4dd)AMB|BGLxFw4^jp4aUaSceNz3S+M_YCzd9PS&BR{aMFXA)smI7x zC1tJ>MbYW9k59Y()i2EmGPopfZzIW5-K!J9HtpUF>sm{cn_O?bKghac6G zjr=ngytY_vA?iM-o)h@&M_ClQ$XKH92T&X_k*_awUdFq0vI%G!wZg#yRU@?!9?s+b z2l_#m?xf8;sP>Mk_AYYP%b|+1ukr}3O_#81QZOzVowS_iN#XOFanT8@KdXq&JiZ4U zxIJR^9HM%>iI^rILq({-KCx~^foX@Uu28HZX3UQBy-XIvu$M7miuj$bS(NeyCcV?R zd<+80%dK?;hIlh@HY6T6N-+1!Oi6i134#cJLV(keuMJSwu|_J)I2(%OUsV1WUm7e3 z3W-3cSo!wF4x>3>P_ZNOiY2`>dOZg8%wUx+`byU?ax#5XEj^aLNw!qZ&N)D7jB+~g z9>}x(G;Ia*p)dWf%bRA~71tfilpNBQsX}VsWpuTyQv!P76@J}7AeI>>4eOO`9@>ir z<*s*_*^8z20BX%w8H39;<7k&Jco6Dsz+}@n^MHOnSNb^^aksvQqq9Wwo1}Y8v~&-3 z-g$swkRaT;M#G4!X*nWHvYjCGTNX9dB|BEfv4(WwRI5%N-*@hUnKmOPix(HB2K>4Q zhd;bu_prM{awLGbN|%m*olLWjn?0KlJURugG_2^QvlOP6VUelKTgecOp<7^vBQ*HE z;IrD-22oARWg%$JA;2`mH)9hYFi!CQ9%;iD^Jf)1$&9GyNT3${SBxutij=YcQ@UF$ zO~;l4l+DHY)vDYg%T7dxt*5is> zG(Q@1|I1)*Kk{3CmSwy)&gAjZPT-^8h=^BN7aOhYYV_R0YL-o>VMhFUfyNvPPQy;5 zOVf2Wpxi|hEvxc5)7~xq&Ooz#q}knp`X%^0!XT7Nst-O9r?SkM1E_Ik$-0-3hSP73KoQU8>rHm5H4objG_ z%~@=xu*lwFk*xdZQ>~B8eKbZ5C@Nb^LcaSb85WSF`|*8HT^7ZZi9L9P+Rz-t0I=Z| zsZ@&JpU!S`Cr;no7P_q z`d+(?Ba3BeB&xsEs^mG!X`1DGH#}LZ6cpsgf5>ovwe5EquQwP)kn3~kGSo}3gsl%T z<|3O97ZKmSoA&O+j;oT{n*y8dMlDKubqm>hJ(P<l_bV`X={%uj6{9yuoxddpmw)Tu6)Cd=GdtgL$R98MKCJ(mt@uO!KF(D;Qwk$mS#dfDUI0z8xSp-I&!uGq4wFgj-l(h7%H(3L6wHX+kM z^OuTw<_+%$rhaeCX{w0MC)Nw$i5y~-thCt!kz(?TT=R1=*Nv_p4Vn8Hdq}fas%!Fv zXXdXu4zY$!L@D72AGMa%Af5A;&?s0b>FF!#IBbYRbuOF(jKDs(0%7wP%_KVh0+XPW zSGNS-ZDg53Q;LBMx%3A4;*$I3!*eeGlh0kgAOFA&71-u(IA#`otnCq*zTe5aHtown>SN z62F{0k|3~Jmnt*|hle!!@uUAk>sbd7U`ezs>KgY!c<$p-$g+VWOJi6Tg$=SV;Huh~ zE}5o+X8-?(Cc3g_PC7GMLwWU^xF!&1KbT$z2&mk5+{tp``GD4^uise%bx5!yH z%#y8V=ybmk=7SRe#Z~fRc7=svy@XYj?|sp*<;-t+(w~M2pDd;2HJNvmYAyw54^J(( z@3aT~&!Rgfo5%C3;O*liKetVL`5maiSKx8Nyc{{J`+o0^`~oQ2GhA& zOxdU?EK?m}#RND@+)-$`vjTdq*{pY1hoqrG`}8KC7KW!^xbFppODh;7cBV;JzR>l% z85S|zv4#>I?8_B2PK~K)Ir{B3Pfhj{E^PgWhX$YT7t+)5&>+3GKfU>6&;}(TOLuG~_$&UucFMWpy+M_gYz<(c!x{0+t2w zF}sgPqK>q${1*U7!Tu#zYi}-*eV+llFRv=aTH2P;wyM@zI?u{zzm_H@0qYosCl){g z3Wa@`~*+NV;z!HUU+}oQbG9fNmha`2-@?s&5j9;&iJ{Xf`~Y8%GoH?W=nrc zTZh^fW7Bz|0*&`_SWVt7>o&5o^U`2Pk*iN}5G_UIs{c})+sufp$lj(`x+_GamU@x5 zKEHI9pgyVo=^=TOmevy}y2vIvk9%p|cU=AW-HbWNT?MFV64pOC@~*de3W*}{vFCk2 zu5ocNL&&WkS0E^Qzsexj@U*tWWF%VFx1kBREz`PFYl zUA0v|IajEdLRmg`>ND)D>XMZUBS`m!q( zxhbLRC&Cje0FR7bb<5>2T7jy$>`I_I&!pl1clgyoLk|t?$seTmKZ2AJA?aV!%|I@`|1pSqIk2NlSi^Ea?7J4reYd%Pt zhiM|7K%s?4S?ZRUjG=^^gYM9(sg8Sw>DH7#mR^?~WjY$8=UNb$i4w21{5ot1VuN0W zf=8gh$pQEOF-WaQbMWvvhS3!|T9ZW<8!R3MI+=>~OVDrr*tI16+-fj=XIB%+?*x7S zQ#ikyW#mZs`asp;BqnqqO4VQ&Yzn!s90-(ncq5bq#6FSD_Z?)F`tgV0O(u4u;b{)O zJlnBEHs5umr3SP{=d6;L_&seM>&FLC0Mf@RSE^c^e4Jt_R)Xmfa1ELeKg-k+gS&?# zN|NQrf96`&q-B^HTAwDl^^v1;)w+26t==J0#F`<+REHMlf0Tfxw!F!+Lt~gd3BZDC zY3^w-mwM-cEEMO~GqVHaPU%JscO7#hR~;=GnF?_AfQ`gR`;qfdA=QQZcHs^otlC8X zQFQ+scr34ZiRJ7AJ34HO4#e#dxwe;jTh|M9$#)L_RKwa?$oCzp>e>0hLWa@7ZwYdw zVd0I!x%J!d6uhqTp1}!&pDheaT==n?6@Q3IOrJIfyXTtq5_#4vJ~`KtQ@fei9|5i& zu&Hj>Dzh<5u4b&H3J)r7jnS}~BPG|t(ibH=m1|cO6t))_=aF^y)Sd<+sr~Rm;~}}% z$N(FDc~RlLl#uTMi;^IxS=ksjb+DZHhP6md%bB@^$k!y~9X~Bfe5eGSA+894vVODY zm0^Cf{mH>^wwQ!`zgcNmK-^TQCqACCkvQROsQzJp*=ehi4PR&K5}195k%7qku|Q#8Gd{x+sA0)c~1DeTKgDWGBj&kbmmT^r}AKCwTBti1kBFdkg_ODXT2JKGkktl zc*w6pVB>dW0melqHw__G*C@xI&!+PHua3paNt}0*qiRV`MsX3D!QEx)HGo^CyLt_r8)iN5sI zLTc^UQ=9g61iGHOJ=NAzuZPbad+N_8w!vH!K8G;5p4t|cRZksS?cm$>RDD>mjpgd8 z{XBv06jHK+X7x>5I@BK83!Wo z{me0xdInWZAl>d{>dKx+4 z<>Ck_Xg!kL&+~HEWpj0LQtMC1-Eu-3=7-6Z+a)@GMRNIjoorA)AfmI=oy>XDTqump zlgWm!il*(s$QlZ=5vam7>S9ilV#p~lv1;K<9zhM^i0l&Zjy2CB4);cUb0M5?Cc zC%@$4Dm+7L`Fo8&qGWBi{k!Wr8DzP-#_NS{E}NwX)pcFAt}XjmrKW{zTK);ocT`ty zmT;bW?Y%CgplN+gX7+&Tl(^CiocL%Yfa!3y!I-_M-gNfj5b|u^_=>qO`}L6XfYet) z>QY`EGk)SRhi5uEGMrCubO>1M;uGQ|`hE!7S!6p@q0(&P6 zog#Ol?m5Z)RNbnDfTJ3NV6B-pU0_JKdA%*T{P$+sykNj)+F+|yM3=2>ZxC3Q51Nyy z_Xvl3HFaiUuaXGPa$)f!z26mr%0(EmM?o#i<2%SF0_qsL>LAP; zg)-JHV%S)`05O_;g(zGLzX$KF zqxrhvgaVjxfc))E_0Hh(BsUh7E3QQk`0@vr>Y+607bX4Uin(fnyNx(H7sl|o=;l9Y zND_BME3A(7d-Kp}4%OT{4!!&U;H9TEyz5 zis%EYm~GVGdH&Xp!E~iToD$R+ygxF#c5X%%}x?;-pu zmp9YFPdE6-NprWg&cY8K?cH`;E7!EzWVpym#s9PcMCr8lV#2#j!`pR*9FZGu6>0l4 zI%k?T4bqLm$R<7!>g9-6IXa@U-$zNmaUSWZ0p+!PyUs4s4h|coiKKBZ>0G-SAbIJ; zcsfd(j#Ja>2AmJu5XD*&GqG)DruTOtBR{zJc3WuB-S@K*Hl zz2QzvB?-_m85gPY=W(a%tflIAU7LXnG3m^?oL?iXQ%Km=R~uovqs|Dso@oKXiYXS3 z3HzdNI4l|!4x1&+%J^x!rZ_u5RB_4}5N#X-4y)^jOiyCzG?>s*CCq$}7k{OIKm5|T zHQoTzm;eI&!Urb3v{aztR%b_4U%iLi>J>gSR&DbxOO%!I(+a1}jat>SlFgTvXP`dE z67kh)Jv^*+9js{i8>zWFbF~i$tv`8NA~@f~%1I*f{$t6viCyD$+EXDuK}o)SPLR>4 zX~AFG9}K~Kksqc+Dh#S^!*VXYmN&YCekWqywTqT54MsWyK@oW!V!N0`2}-O-Q$;rJ zsrsQx1Nv7~qm?b^c3PDjfBp@L@IXt}?7HSdOa8r$bE2AmD!Q07W}cLtG-g^BP7p>} zQCLp8w5uTTyS}B)!fLg8DOpKLn~mae%fj>Yv`8ZB0EZN{#&_S9MzBLaaO|$hARUV* z1qSLrlE>K5SF{v|B!&4wFbHXANoZ&@O{LfqN_k_OXhDV+phdU7E;>HQ#Ks6Q@npPH zXC`(6?~b0OZwiF@d(;x9n)xKD(;9x4TqH4o9 znD4BPn?rPB%!hlZHc0=J2UfbAXo$Of%*bafQ;w}a%O;_@mLK)@47plJVQz zyO{+)RT3N2(PhI`$?vnEI~i!?k{-&gnVW3?>5Q(@IUciRI?`m8CNn7hO86ppZ?JfL zfGw}-$7<=0s0=3w&)5-FW5{{cuW(@b>a_16ON z%S2b`t#WtJ> zeLkwLs#*P~Du0E}wEnV7if}z*c`h>|mkN+`FnaMCr}K=_6m4A007o*85XI@pd(CKBjTFzENUebkf~O>Id~q1xj|WIN;-BG1rZVU?vVcw=q>}|Oqa%Kl@XD6SXP@K ze-V_KSWnWpcPWfftIy$FN-p9|K}LE(i0urrHL8T{o0ws_=@nHw++XbnXE?VSaoF{(2a(0sQ~ycf?jNnsnr(*qhWt+3l6@*1TPc26bLlp zEHvUgxYh>`|(T8+g;*t{8~GU!voRFB@<~kj~g^-(~-CK7R1m%dLJ(_ zr&}j|q7^UC&1|x7g=Z|lFvPh~>3N#u$1jj>OQ$u9b0HjOT^PQ!ZZo$?aQ=%58S+>1 z6ApPZ<3xbJ#X3D`>a~Zy_MrYDxqgAAN$liiHi-Ipq@gZ?O%P$U!kFuKQ)O-Q zv<6!KJndB>dFjMg6pK`$; zN7P~%Z-$?E z(uk9T@t+E2WnUuNcdPPiSvsW?eFs@%f8QWusLu^wihYTx@98H#@~}grE4=J67x4 zFX*Ri7>Vli_!b753&PR<{$|olLD$A9@=sU9hfq}CzSgVU_hJ+@2fw1TiQ^vC!}R6%eMeUn|bYfkvgJo}1oNIbu*cz{#au0kRtw=X9k`XZey zt!$RC4c(SqpY3oCg0k_nmBp@9S@^I5x2B8YJ(Nz%R+x=#?{7LNvbI!QfRQo_M}UEb zxRuvJY~2nkF9z-Tv?r@XjtrkeB{IJp!E|oiNMZjru$K>a&jv>Ru~IUFD2tLQhq;yS zh=lkq%qtjd4?>XXm~gAI1ZI)DM7`Bvp;thCOgAPG?10+$yV0)%WoaQ2okNTbWg68G zE%>aN;YT(ibA``yE1Ca~ws(*7dfMXuOMMt>OfDaCoH+&!6QZ2nlzb>P^%-X9NaPY7 z*Ic5LMsZmvZa#d%o6wzu%wFOnkqO z?;pR%gXZ(zd+oK?UVH7e*Is+=y*ZDt%Dy@ZA@66tZeLo#SR`28Jj3ADGU3A1e3?t`4Do0(q%G~wF9L*_Eo?`nU=d_?!-(4=OX(c>YA-(%c6bT?vJ>FO z0PGwV9{zl{=t@2fqioy5_IPvsBT;+S(zgU-?1&uizgdp9?7(&{*laj6Jk~I1_*W0J z)ja}7!hNmWbJe}(OOwL$zJL?`Wn8QqUPP9+^GW@=KSk7XD<@Q8rSM^$@s&YZO^u##z{Z zI|7ZF@il8&ryIV0&B{M|uv53#B>y#=|-eS4JP-bAyRQ)_MV_Zr_)nkkEh;B3+37tbsfGHxWOGkHQlIsc00 zkVYZ?(MTcS(5rh@WtscTCU}_ITzE}6jcNRv&ybV62MNZoe;QeiQc8Z&Qjw5N9u{(j zcuy(`8MmfiYxFlv(8b8#rb4#JJoCMkR_|AK^%6HjH3W|U3?D;7H=Ak;M*1N5y{)Qv z|Au^FlCpiPQC@F)_Fm>+_K zY^c2p=~xU1ke=m`+I^u7!P9-!Bn?zX%W4c@no?t>6xdJbhKQVIK<`S#vdI$;a!h1M zlgY~okBd0-J~BZy1m_vBT-2Pp%K?txdzhp|08mM>@nGr=4Sh zNR3?biFS^IC1ADsQ#T)CjHX*sZ%FM?&D{W53%X3>S2K>8QZdHjb8tQw3S4XjwCfyF z$1f0YAA)6k66|n{BslTR4x-;#H%VO`J#mGmi$ViuPVd4wj58&?gA5W)gMMm~rf$xY zzsw)v1HuMcctLWFaKkT8RY~Zm{!L3O+}XOdPq@^{rWW+lZYskeo-?B37KhZ@ z6gJgRMNz<`93kJlD0)iIAkU`yCVdx10soWMxG3N`ZYEF^u8RVG+T{BGw?+y&T0zxJ%8{J*zn6g4-`9_f>pU1F3 z_uZmOwPo=+!^(n`8iEgxHYLwkpG0n`&3F%Tjp*}Udx1aMh-IwrWP~>amqi3n z@%zDnApxfv0g8SgOACh6K@dP z!Kzd@*NPMAN;r9(oN&a8K#DU)=0T;|GhTp71X=D)o+8CX!TxhL^)rm;toi#v-DsmL zmpp)yy0tPo&`A6cFu^%&COpwv2bcqyQ1~(0c6-6@7W=^?yC2yYRJScHS+LaYUfb}n zlW@a$1zM|os>_Nm^}$c0r22-=bD|dPr#s0McH~}RvvsHQ^8eqq;}G-Uk<&FrjOVWM zF>R5jNk?{SHF|HU{^VJFi+j6qwZ3~DVOS)Ya>-U`?h@Soz-ds`^%ARO%Os3WSu;Vc z$})lN4A8SXF+~Lf)fw#oRP8rIdsCuG$&yXeB#C;v#SzEw^1KarQOlF zlrPhLa>_r2eFtgfEA*%ICbDccE7f;6oArkMEZ;b#vWl_D6P5is>B&mAFYRAFTG_S} zv`GGmBV9?!7K^Gh7{I2xOt4q;FWEvfux{@uUQEdZVwCSO;$E}dAk7hO%oIL-IG1W!Vd>%!R#+HD^R_V+N)uQj$@D|4Z$rp( zZz6Ta+xp$*S-sih49iQmUglC&zZ3oWU^WX7UT{vr94?>~NpeTN$w3X{(`xt5We?Iz zu04@|qX9$lBKTiu0)__pf3cjNsu5oo7;p!kMmt5OQTkqf3R#8LKsd}Afq+BOsgNq!x zlY_QlskV7UXNO5&(Nst5=st$+2C&g zVcsY5WcG#a>f*y3=?K9;mI^%eY|gZ~K{o`ui$>Xa-tJ^0;{zd0ZUG(W0>- zQOYl$W`*O60m7M9f}KqrW+fF{aNh_GvQ&*oMQ)cH`6A|Fu()a9UkGy;F&$o++z|NW z8ZCC-hmtn}WR82*+3szhHGR;G(F9Mmm4vG7NZsoWHI-gL#d6&>4{|MkcT0h!hHrjP z(REFJq9<9Q77QkOHd2Wtl7EW#CPs37$XNK9&dguP;0lf&W0I#3kw42?=NQ~F4L8f({+ZQnml+RK`%X z|I7^iu>-%sSXcJ&@NI{3qw=j|I2|U(~AcxIU%=F}h=znt{s_ zmaDp(u$TcP^MqGBgT<6E2Lc+@y5upTc&DUpAP!Fy^AW*Op*lE<(xEzNKi={bth;kJ z2+w*K+Zs0*Avsk$pZQs1V)0m!-kG=oRsYK$CGn~BV)4QSb7;0AsAN3Q=1K|hrb|3R zTFRp4%mYu!WS_v!U~V`J=Ymb-WK(myny8NFiW%w-rrPy74Z%$U(4Ngqy?dW=@fMkx zBS9swcF#JhE(q}`&g4*ol#(UR^QW+QsS;TSyrdrTK4t9Dh?mIi_5#B?GqblLjO@~m zpkqJ=_k}z!;@eH@vpBx{8`C=6;a&h$$UT^1Pm7sd9RmzAJ7YroEgTxVM*dMyI{zrw zfRr~NWNuELr}Um3Eg;4^b)Q3pyKWBY$NIb4{)~3k6I970S<~~2Q7^=kqgBSaV54KY zRpH3VCExnd#YB=_EuNH1iZ1Z*0vF|t@(M*4!@jgHH$ML?!*xEi8e!M(Q^ zQ%mnwS%2{aA!7504Pg^{n}$v72Y$!l+%QyTv82GV^aD^EzP=m2-;Ltj?hTL6AV(fR z`Q%KH5M9LsbEXzmc-N zNkbW!B9KBz8;tuC#;*t@3aT*_q<4VzuG*|BYZkxq_mMCnoA{&oofb}j?6f~`3V(uq zX%S7SOBSgqv(;GFq6>ZyFL{_kE5*$0fkuQi$e1H-2CYL#4x81lWWnQVSD)=yp3m9l zVXi>TP4SEZ!$~e|+(-kfvp-?u1QIpQu!N0sBxF@(+_-dhaT>%y!#5=QrU@9N(+BO88Ojo4&Z zwaF9^Dr6O9+^8l4&2q@UG+z>8v7>?T4(k6#UyK$JMi*9B!4lH1`;zbKo)ucEZVG}f z8liQ8!E|3MI;SoGKDWHO=ZB+SFU0@aLTRq)hR)T_{jcAP8dX*MfRT4U2|}{?3$dWV z@T1XCuxYI<&^u4dhj1}q{UWLH#xEgD{>kYhX%qL~#aK%wFJ)JIf@zIbwR=+jRA3n= z7MM^DoQBZTz#xNSA{NU2q}uqQuPuqW!TKdHXyF)oo@C^0@hX??f$=X%xJy$*?bl4#w)K3_4=!_flxZs6a?JC@+A7R3*BOh@hh}b-wS3+P8{?DjuuD8GX`9Pv3tj%*fszSkvs|$6a0hiW zP{E~Ah2+0QK6VbS{L!bHXgEX2cZSfvFLh9JfpX>uYGnds1?|3tJAQfZZq5YBsd_l}Y=V$6RyWBk5R^TfXw<4>i z&i;hrCXh(ntb8bLuBNQ;$KnQsYH+aMMG~*Xe4Il>$4xLI-Rv{_VyC0~nWsJ?+|4*0 ztn!F=qBfho)V#ht>fDmV~=maR!f?v8DFd&%#+B`@PzJg^H%1Mm) zN`IV#d{>M;Vzv>A{IY#{aQgm0WK);y$Ht$Q^ua&QYt`ym)J?0P6*z)3FW^(h#)Geb z#GXdsrtT?c$N0i$i4TC=N5Y4TtV5MuqU;A;c6YL| zzF*nbN|&5LALN4T$!q)%P*gRDssMP|0epQn<#$&3b6ok`tXkXr`#M;yTunwnCAmS* zbKOAePdl{4%%-k0Xsl!QO@jx4HjTdO%hs(N%{w}z*SNOS2_4eYD)@dsW0K-~pry>w za`x#)>^kzA4gvYYPznc5P$_F-y>hg~nCo(8o@oUhCYehT_irk1+845#`ZoQ(>390k zM@0IieISQUt%qMtJ>aa7O+(s`A%M~MzL{4*v;hLWYI$=k4`_+82~u!c zdF1~?a}0P&Gu6^Bs87$z{0+ilpM$$NKW zYP48yIAwOq{0%UT@W5jrO(EgSyo-{CU)i&tef~RD1 zgIa>Q0^)p7NQIF3-sKBKPh!PC`ID*3dndm%;H;q1h2F`X=t!A0WNSf0CyPO7Y}c9- z$#!PT=v~NDs~CgM!-#iP5|Ui|88B|~bbGvbGP-%MOI*YhQtjd532R;JwvxKz4VepU zOWq0+mP=wu)Am|U8V8L#W67dPjT>E$>7}I7h?a>f)UA0%)L7by5&P;sP67)&^%8=C z@f`@O;8bU!4NtU(cOXC+HL@LNa_W6yOk8iK;)kl8Ik^w`-T3-1Da@kA1Xe}3Te*F> zA0knq1*7l1faLPtcUW$F%DGvZ_fJTx>iPcY-GSOgb(l+xN49v}@=C)hd54n!!;{B4 zj`^y+k%I7^X_d&;b`^3+LAGCrVzBs;11zs#V>(y9KS}WbHO7F88Gd&IUBkR=?JsTk zH^}_*v5$pA&|MYNWo?t10$c1kW#1b{KCH1~iezpD4Y>Q3?yX|sw$-;bj4?(TwoLMz z|EG)K2esY_I^+6V1kHoDs-)kRU^Uq`TblW0Mwi3o?t&{gHE-w2@_Uu;xV*dkaDWj? zdkSy4V7ng6M^{_aWPavgzZq8E84-Qz1tKCi|M02n@PUp{XsgAq=JnbN@P!a?eS6o>ARpyw%})M!LObQN&vrB7T=j z%U=(D?fxN`sImBV@JZyj4;vvfaneI>=6N-MS^&gkzf00cR9~5{B{wvSTafr{nIjRL z$4GFq#Xs#}H=M0#ETCPxuSn(dq}fpMc6`Dl;*ecTkht%H9P~SmH?NJMN$whDUFovQ zXk^7B2F|3MOP)(I@2hNc`Ptpxu{*4h%N{fpIopG26haQwAHTF0fV4s9B}^UP0>zT% zY_gk!dvWKG7a_n%03?W-Ms}odQ#ZU?-vx$+s^xplrgdwvRCW{R z!6*XT;wk91y$U#DQxI>tIt7GGJZ8|%M6*!&I1!<5sdw*(MKF4Hn93+NaK!T^lh>g3 zbP*TlUToGRzc=|@L&6^B{v;pZxM#|1KdY@Fm<&x;4bb~2je9+W-S^t^GczOar$HWbA8I5Yuc6_4ZBUH^cr$Q4J-GBU6w0OaJrOpgUvkg z&9wl}&IQJw1{51}zGf9>kcU22lcA6~-!JWK#I6awM>2%-bB=zy87y^!3=ZGBQq#Zh zy$cHSK3c$3_dn$M`35=8F`=oJ8UEL|EiFzQBglJXjyPLz?9bSOUsE?UYkr)3hnwcz z%&o(I1kn=IP`(+tckazrw5z&j*U?3ENid*Pt+NAc;Y{xAi;vlq)Vy8oTa$9hj!??z zJ29NIpLTP$y}}BYyq%1&=~ivz@BHW^Yp6}zV}whiWdn)!W4+}**Hq$gX_}?>~=YH36C{5hB(E9f|t`$jV#!sN8 z(}WAPgL#3qB*WFN;$y;oV=$-YrYD#o`kUyEafn@P@EQR8c}{k#vX!m* zIUG#Ync69+jTuc>z^I392IH)lnQ>v`E~0wmPKFn=$b7?{O}@{nioH5c7xBb5`*p^y zqaCG~%|MpE^P%ix8>NsAv38I`pxjuJwqwvEW>`zbtg4k8X0~fr`~cWY*@HhL;c!%D$_-wj8Z@j z0t1>%(m?zJazqbm7g$^GV^vo+d1|Q|`GW&F+d!}a0Z8ON2n&mTf3f-)@ye~xzIw0o zR$Vb2IeG~gcZ5SI%YewoOD92QQ;V{!WtnwpzlM`ql?!2pQ>F0m4shh&M4Q$g8#0o% z;#X9y>Npd#p36(F{TR){f$OP2#llxoS0UrtujFh)Wj%j6%u~6l=`e}{r<&6-QIz8d zkn65wXV*GYtI1vMgJa*^AEXvpOs~$lF<$e;%$M}Knx)cvVq4VCD!KNLcvOfAwM@j< zdfVvEB_I1QERYjvgLPSHKaB!E;n`r28crPJe$L|O3GQb-grDgNqXFNFol@q ze%YYj)rbs9VWMv&jbq8KhAE*?Uwbl~L4izuK*EG_d{R)h4*wUwP!l&6`Do4NRR zp8gFF^f>h=wN{}1PS`!RxBhlNoFo3JquE<0fpl=;wFxW-en!bXX46#a@mY}JcR3g+ zycD55cpb>Z0^j>wT7q~EQx@ytAP|ZjRg-t13{FS8Ci+ZU^Rfr{(Rvka2>Ln{I^DVt zN;dSDBuQ=Br&~Rb^mXc>e~R=9Z_^$vQw;wjpxSC(W79Vtj-nG<7X-=R7o9fG{!l8}Q66(A(3&yhEB@2iYNR;+xJ@a(EqMkig_|ldzeGUP~0; zJ8Y)dhMA4_LH(m_t^z`uMvupYzOB}w^tk4CrTMSD)1vwH9D3>i3)J?5cCxmAqq&lE z(@5yQ%A&UKX!SP)mxP4T_V3L*&iPl89ND}FX804s!)glJ&ik!AjPx+g4o;(9SV&*pm^{n)(^qG_sZt*qus<%_KtT?@^$OVW>-xaoajm7d1 z-h>{g20@?P$!L?(3Bapf^Rm5(r1i+p3{GL%gYE-540V_7#cy*E9fFp5w8V8tcq81Q zV2k=k=RIb9wPi|^QT%y6m4y{{dDpzyf z>(5$!WXChmY8Eb$Prut6=w5CI4<1Jd>gvZt^ylFV!_v>3-aG!o~uUcXjKWyF8Rf-emaOxgXQ2IYn(KA|^tEz(#ncz;^ z-n0)2a6oOJlBcV;yNZ{hj&Iw?@3-C9J{erExnK+s+T=}4Tk9Cmt8znavE5Mxn@u4G z*YDW6)zqm|Bd*~=tjVzAp!O^k;@Z0ShUj=d)mHCDKK!6P}xz+%rp zuKXbqVx*yKAdPE)NQz1VEcovix<6yZUekhxAV683rX!A(>d1USZI!EY$!Y;{&-)tw zWHFnY3-X2PzKjX-Gg|waAYY99p3{{Vb1Kk4?F}0<(esm{K}398qU`dtY*DABHA3VB+fEjz^a;y zlgtInuXzk38`2^x9NT)<&o)?xqxtO2tT0lY*1)j;kJ2vKa9pc|?C70>H4IG5Z_HKVzu($Kw{%yjtVN?Kkb>ajWNh z{z|Eq!cxKI^9*0Q=3Lq=#gYhl7dO47N>E%JKuDaZ4~uPYrZcDKMQy_W1TLM)d0^SX&r-x> zi`9tth>edAOulXsF0`ll9id&vI#kP~6%_@7g*lV#uS&ha_NVwk{wz9`3WNXbp!C%D zm6m;&%kHob*{3Oc5!uan#}0rSz~5?&X$CG$K!Y$KMUI_of$d<&aDL8y5}t?V(?nOoM7wM6gp-YN)Prb*bX7mq9`@q zrmfP?XV52p>H@=Ju1H(rrOs5g^G%xHB2^P7Xu2h?x8NHeVq)f-V$jUqGP^QuNI22} zD(4hVd#`I09I1uwwunMZ1N;L z5oY1%lBcRI4BV&H_ojWXF>g3a;*WD3nAx|p_bN0OCq}f)(JY}|*2L*8b2Qaymo-sU zkW;eY%XDjwUfLUpX>QjESB2u5dW7N$c@ z?lgGnV?@Tpn<>$mUAV<1-N-q=+*S*DTC8`B?VjFu(4`r>i-Gq(48?LC?Vh}+IflF* zw_BG_v@HRY@^C;Dy!5k(i{ZwwA&{$5Sp39-Rbo6ofvowqcreoBJA4S^ zWYF6~7=9wfvv&l*+y`lD{JE_S>Cvdg6CMEfP5S(0c8njmVSJNx0JNPNY{?$F)pRVo? zcOWQ{PODwTPb6!EHPH4Pov6$)fx(Xex%`~CLj6^sJJtPKC}h5oo@LVgqt(U94R^zW zedajRL3T61V=)MxHYdOsKqCry%=V5$4#zj!)joTh+gk z4aYan0L=HUorwM_rl|%Y#s9mlQzX2rqGH+P{>13Bqg3{#($&#|N&_Ve%;rH1&63H_ zJ9&Ho{e{Ha+G6pmD$)?_X~1&hBaZc>ccspCNWGLo@=jnf%bG@#c9^L?ylyfbCR$nP zTiG#fAO)24`Gusbms4fToaF2@ReuJfBvjKAiHP`#R>3Blzt~7V)X;&qr+xrW(en+2 zA(bS}i21#KL{8Jhj#dV5sc9l7Qu2P8S==!%R^jE|g>v=IE59KmPP}^mws_t7|5P$w z_)Xln*;EtrF1vGymtIyYVZP?i(i(80nDUze_8iYjhWndO##T@(=^6Z;z=oPPmDB>< z_uiitMRT0kR%nZd3VU{@g)wB>{fmlOD{^gSw)hyEH1Ymqi_^B6J`THw>#rohm|{rl zIT&}|Qz$JbBxd+b2cMZnck{zs7Bf3AE3~+)L>-X476>QoV{d}E<~v5}?Obwzs6#>H z6jB(gFu5?+GPg}6f0M3-EP{fdtc_Y^_c|Qwci(KvYH$bkf~tD1AN59I7;BN$H{H-h z8$s{B6jfFG0K9vT&yaU^^F%B;Hu)tE6EvNokd56JYVJitsoV0Rv^?0mb%9A`2P(T( z`(w)J(@$Qccy=hWPTthC<=3}#WR0*nYvo>BSj$?urh<21jKsbm@cKtXlUvu_4PU=E ziu6|RKKjKCKO&`>|4We-Sb^Av+ZiVLYi9beUW4>qk%X0UC5cmSR(~Y_(>~0rClCMg zFf@880z}ppmnF+CdB4j&hUD#vt%N1}F8M%`I}{|3cFDU+{ZrL<>I!xB8Kg@=*x6^1 zohv_;B%9^kMerxapLV5MulVz7ttPt1pY}FrY5196x4DPOnDM#YKAj2U#iXa}dYjjC zCbDRMHHCjEj7tWJT9 z>CF5h{^+LZ-NV@gwx&KyYQ=93frhWJ^_ba>xd+=jhdZMWVKNc%%JAQPx z{c+YZ-#o7xO0S|rXrej5=a;F8zE@9{%~e?3i>-k&(KUDRZSAvfja2me4K#!IP1@m) z)4-6S0^-G@(jGd=Ds**_%&^>i@lbj+T(U0CN%V2#&sL++5|9ymN~|R-j^jk1%~8g5 zR&1pUrS*yHGFUW&_iR=%B22Hm*qdCpgM28GDekMvgct5*+g8d7 z?!47t{C^cZ%`_FgP(k%*MWopA#J0GfRHL(XLgzFV?~$j5Ly=u0V-MMBe_Qw2s(f(H z7BR_Qsyo(izkx~d9h5lab3e}%n=qO0L<2M99fB3Foe;yK2D@j7QM?}@+Q;j;anzl0 z#F`PvJ&Z>CbR#L!dLKV09qgjk2+M?4BZq48<$8a9yaV?NXa>{Gz2U+oBC%y-24qNpPVk{)%0&;;u+#_5PO>0w8l$P8y4(HZ*9 z7@D`zb;OQawc;oiTZmIGITMhrI>PAW{1zo4$v30 z6Ok^UoMG^UCIf%A2BPbTg$zMDVtXqYcEmw6IT{Vau8TY3IKx!f5m#!f-;6^yA||LW zex)Opudt37NUd>4bl}5v#B8c?9RZyhpte`)%cjWI38gy2v}~P=UQayA*ah}^%S+65 zUv{X%Pu%Oi*1Ehq-PZ=b!rP%OJ!^=<5KvJP?D!Ma`E^ssKHfhvVB)>b%xBZdXpyu( z)2d?=)-Qi&x%e!N?IfCppyc?Tt^r`s^F@w>DT>oX6lu%>4n|}d%yJ2hQ;)v)*<|&3 z^0{sK!%=#b_Dz3R`&r={#M8!9re!uGeEyH>gTh|yU-&m3 z>BfKVN2pU}(~ZrHbRf9za+zc{?uxn_NTvO*$JWD|CID!J)Th5#M+t&^f3P}TN>|lm zc~U3tSF8A!RJx@ley@5$%SgejY1Py6<;li@pblDNFiky`Tcj`M|Iz$Ep8suK7umuX zENlw?%)R(VoJROl8ianAE+mA{7&+HdLomU}g=tgfUI&0}(qJsC$6j|v zM&xg3`Jj)?>*PmE#V#T1<>s>+H!Fb-c#<3z?UR?(C2%1)f0Z{t_aN^>cy4HwF_ZJJwG<2vx&n@R4W619?hDZ)Gy`#-<+P5 zI&%)TP3^YupLd6-ti#nGj=ZS~nplRuZ~Y?aR#(^rNM2{SizQr`QKu^DOlG#cBO9 zPcWB-*c0~A2HK6*w!YfEd6JbkW_sQk{7*`$x6QDS6A>o^+WA(JwR*rcraH9U)xrn7 z$(Zc@sjF%&KCnH!9w=VF^{sWqT9Dt~ANWdHl`R?hspV((K0--n~@21M9CK-Rk&2SHFp#Y3Cc8CKqjl6Am)glJbf zuQq2?-oziS=z54h?B*(jWh48l(yqr!2>jG5a>{2C&+!K$*OMu9`PHLsD-)54Yf86# zG~|-Yfswpq6FXU11k$|pC3Q30FdIei2NX=uxYe{nF1lqSd(h~XS?P>)OI7AAsm@5f z46q`_Tm(Up}#!?Bo0+7L9 z^JsBw%jfYpp|9fI(YK;xd_9QZ86asXg2UO2W3vJlY4v*y5Y>2d5XtwsrE5-=yM(JI zb45{F>btCrf4I@RL!amRcZ8DS*6<+hCojTZ#TrZ7HtEbR)qc-d*8}rmD0=)HCI3W5 zUcd8@_;b3#5j$_f?=q7?Qy)&*JK3w8H(_kYR<$R=&pOA?ZO4nB6I3I{R5o#s?Zv8$ zb_8EfA1J4$SA;@ih?qh<3D{@~)y9+b)j*ZE7~IlIe$wLX_&H08AT^l%nZ=~ov^u=N z`PQ^eldCcUyb3^&1%Ksli-$O{GO-ufIOV;VL_ecY`=w6E7l|Q$YW@_H$HT5N@tym0 zD86dbKclz^?Q;6wffy66F_PMB;;zE%)V`~ z#Bj{UaJZk$ULW)IPwDKHOiH2N4*HYLHPscQR4fv!slj5Rx`gEvv}YSB-21ga{c~l7 zb%~KNw6T4JUbeg<#$IA}xmkeW$uzg&fVILNTIp_Tr0*SW!yU22A$T0H?0NQK&h5=l zMs>6xYY3)WXUaM+r$eC36oJ{q>R$#pX`Bb3T=Xt>d&A+>gLK3vk$bdpMbsb+N<6LJ zG>Cvxr~ingC0EWD#SOu}VU2jAdjNBVU{u9y^3N|h<%RQ0Dpq}6vh4NNUzc3Gzmz>Ps&NUmFipff(EUR*n*UrOA0<{G-8i^JxF2ZJvRO3j6N5+zMXGj)#i77?#-rleHOHa4^72(h-CaM z?!6ZY?0?#yeDpMYRiVTy|5UcyX!vV*I;e0y2VZ*9`1)3(r$JNwSak?(C=oUem6cqp zU3w-)DM=1Sc$YFL+y#;GW7RzUlU_E9d@yo_gx)N)jP$Q%q4;y1#V`b|uC8PanV8e3i$Z;`Q$>ciIw_X=v zR9E*?ergXcC#f9)f>M_rE{(Hs6(iy*c7X{d!$!o#K**xdSlu2}3ZzSd=RJf#YqI43 zR4}s~1KAN_iR($U+TXU^wUMrf4`WIBts(x0Y{!9G;qz0syMiH$KZj{Hz7lWGi#X6- z!fo!ghy$Z2qdVESBF#I@$fDUbBq{=Y$`*MPC;hPJ75nqCKu*$0KWsOuJe@efes69w zhUN6;*0sCvW^f4+ChZorzI|X(y5xZuFDJGEOuK+->l;YZ88$y(XHeYjH1GIPkd;mL z|4t36NA0`}#Vys&Skw54p4J#z!Q@@{LdoP$kT2RkO`|cxGRKYrr88NJ5J}zzw060D zZ=A|WS7SYK=7AMmL-5iku77-QPaDj|oz{gw5yZm=q5Ep9C~re?HND6gis8tN);F&! zIhQW!M__lCg8(vfQ4gcwlLGd8Y&@R6K^tO4R!#^dG@ICi#$q^4C7J?8+$F8+d#f1< zI8#MCh9@I)`CPL&pmi^!WMy@B{JffsLTxsGtETlYqV!N#`gR*fE+*f0v70_N5va}c_@^Tc69%^_q{B18V5TNyq-qOW*oluh*!*rBt=PIQke8}YmOkMv;BJi%Nw4NjTW^|c0yi`uaR+Ux$| zQ1);n8=K+_WX5wI=nWjQ!FnqmA`FQ4Z8D=3H^*dCDw~}$Qr^T#KkPN;m_?@_l%8N>zRMB| zt*yb!pnzR^y=eeeTZb~s4P&Mbp;S?A`y~p7S~LU5CiWSo^bj{D{m@op=!Z77Md?&m zvT6^|T|Gz`w>4nk`=zTMHwm*9RkPP#a~l9kPh8d>va0+O2$TBpoH5&3B~1yV$KlDn z-n6jgU>d?!q&qdsOpf4QP9-*XOGp`nkrrAwB4 z35+=oPwvoopHrk8M~JB(f-jfc{Fpkf_(J~Z0C%=_LRDr*YOA+3s7Z1*p?F7rN=)bA zC*UXEmov+lz+7b9a=uu9GVMcD6egsfvWu2TyD`<#hln!g+^9;?KQPhfCt(Zz)m`o1 z3eKr(hAX|CbjY@Ko6VDo|DZDdZT^f`#6WFhqdUITX^}~r+m1OCv%{?Pb9SAWZvA5J z11&YH{8O-vy+4??U24(FKRzl3Hv~giS|robY4_|E>t7F!mi0BUjiHnRMg&4 z5dfJllWEpN6IxrPhhcwsAQ^2nW7K1 z{73(dwES!h^=$DyFUb*8k8IoOp6+Z2>H(r(7z)EE?<6d5ytUQz;CsJNRUg)XfIL_*iMBo;7vs&7u&K+rwW#Rs;7uYa{y0(1bWPtW}04tLnrVVH*|Mu^Wvr z(>#t%Y!sh^^!mJVbK!(qIq0b%2C_HpGHTOsyHBXhHIn=XRnxFBmck6k!AFL9L+~=_ z0C^tj9u;+BT9h}><*g!bZp*ye$dlU7CZB4VHO`9ZFx(#26vemF-(Hhuc+)D{x7QC+ z6&cvJ6Mt9P>9(58Ra``zxug?|ezz!zTOOM}QT!yf4ftwj5pP_bJ+DL6q^mmNW$;r6 z$_V8h;tRKFH9D<@esba*35L8n&yrWg6H?4;-UHB+OP)ub7_l6dnyKU+cc~PXTLTVo zC7b#fo}MwDF*bF1!wtngA&LnxilPD(ZNoz9kRpCpXGY9{l9Z?vasPV=0(`IL5^)C| zi!ObgB(v&Lr!XT``RzN=bqCQN*gg9*?6P`JwB(YH09Ku083XxkRX69bWZwGTEOaig zrvgjo66Ld$^G>P<$aU|BLm~Bs=}PaV3&e+^VfHg*J3c%^I!IP)zgxuj3L)+^1a5(Q zxYGR8JYmWv8X4PZzlcIdH-uE;yQ#Ma*nWA?ReyR|+AlrsBE$dfMl!O+k2k3?T4K|F z!Qy9k=v*qpG?!dR25-A%!)IHI(wW{xX{p|w2bwSpWYS1>Mh(igS;p^12C9Cu0>0#V z44ZVvbVKh7UbLi1=`{cM=6@Em>8@;7I)~H_>CA~m=_TMhw5uT<1yXNwh)569za9Rz z_v}G>EJN>DDf?Syi|+7M+ipUEU-d8W!+V}0{1m26@`_~sLYY66r89k0ZV&q2CQhC3 zRsVyhM&56|L5`=EHUBPbBg-UA`(rDDcJB#Wo9gUr#h>X$?4q;8PQCNfAaI*bn2x(RX~ z>3aE2H-1%T0`^!nBJ*|_uBo9Nv@Xrsn}p6?b_KOTo9K>dJKNC){i#p>ZnKLf5*cR% z@$#o>*QWNoX17h#w!+v%7zWQQN&bQ{R`n;reqeAuwY1;AD-x19zH2%&petW=?(zIT zfO(au;mq;;KcF|i>HGod@bu`UhOWFJ11`;0(-FwQAD0Q#bdF;cu0 z7SzT<=TI_D&3HrH_$SVdB<y7G5lb2e|cvuh_PZd~x>do@86+W+mT#J6_>qqzr@$>8{LbjZ+*k zccD;h{?q%nU{y_vVWf!Act2ffh~DlI&=Djw9fo81zYMD;3GP6Lg7+^3n_?l+s+Jv} z)CK{tL_&o}g&pl$`z zQD~AqjbJ#hO70vrP%A=KsLJ(A`&kJ*YL>p%8PiepLW@uijMyR0O?utER3F)~UMtXo zs*yyLC_|$%u5r5YU)%H~A8g4A%Xr_C<;Np=cT2|jO5O2^n`gHKxg9k*ls*VbH4*9@ ziInhDV`UNgUX`nMR9x+=Z(Bo|q-W3xKwN+nyE>jE3)^89^^u+%7Ny^1MHmd!=B1&^ zflsz%_441%Y^a%Q6B-xUar=ScE^TMk8ga}gvy6eZKUOmN9u$X;G(j{NK2Te^|AW-9 zL-uoYlDD5@Pnf==Bc|Isim;f@MmigB^G-F}+kJW#s#=i<-jxZPk>IW~Z&KyAJ`9^~`S@@%c$Gi}@*lN-~ zM9LxDk5(#t=M%eC#>i}3?FOLytcmN?LfzU@C?EESt#t{ACPS{8Z0jPNX`eLiYrRwc zjVx3@amn4rBNp%V=C>++($bAb6_iD}>_jCYftOHuUW^u=8M9)L%LsXt%V!*68B5t_ zoB}n6kpZ7x`(MbX5N*=hBqm`oiAm=h5#CwCV@zW8AHp`i88Lkihin^=*;<*#**eVF zw9LRH!PknFg&d&O$E($jZ{{g*9`z|2U3u>5+2O?9cR3l-`fX?4G-}~Q2yT46*{mZc zg72MjzHIRSP?Qz_xg@*~smNsmDM)oF?t8^8*-P0@z|jZWk?u@~-NB=wDbry!J#mMK zk;bGWam;LvriI*w=+{=usu@hLPG`OGH`fxaz2$5^(OOpgsFJhp!paO6Q$4qk5*WGz zFmw~wo1tqy#*6W*klL|2b3s{f(Hp{w%5qLqY_}PUtLYjIvWSQivvE19I)rFr}a;IxU z=rPD9R(>Grqu0R?F(|L%j7V%knVC-~xqs}?e1$mHFQ=@`p0qpFa8>+i;W6ihpYdGE z97a%=JC;9C)tW0N)x~jc!Kq?%>0V^$NDy18-oDi2nu2IvvPz894Av=1=A5@Cu@lL0 zyc^{vS)DDnpe@kA!FOlmIcU3IzV{~sWS%OWOQ!K^KQvCs5`2{KMTq@Gd$OvtBW6`) zDlPPX89yYMH^L%*V&WxQo1>_*V@>8fSTi2i!+5OO(hnH-x#T5QFT0uH83eWgu*|&o zWZ${HMu?vde;x6kNmEA$fFwpu=0NQidI zbLBHA5!Vws@ydArNQffiSx4ic+qTx|F7p=Y$ zzaVc@cFljkV)9o2Ap0%t#|dpxPbxt){1{dhE(ub9Q%39c-M$Ytki+CLF-{OwBusD# z!7=)5Q##Ht$rD$^?L}QebcG|NqZ!u3VE=;T9&o!xtG1;zAWR9E>eK4}5F~U586;Ad zzIV;Z@ZoMA zVA4?FV@=b+qlSocrKcN4mh#~R#ZMp%4E9-&IYbad- zWWyh5$#y{ATTdtTD_H`=Heq*9aQ6l%Xh6O?>*Xh{oI+y;S=~%c@S41A>VtPo_xQCl zC^3t&!L{3H@!`GhCP6wQ?boo?$U(ntDU3;TNp+@n4jna>;veRVQ*?k8P5ncPj&;UK zA{`gltJAF4U`x>1D6u0#ledv6+NQjSH3lOLZ5Nc1+vh3m1w2X-c_6{V#R$3?k0l=; zi6eyD1UWJH7V80{CNf}CUt`%*_e+ELlTCJlJkChz>_p8BqzTM@z|4MT=#9Da1;gvH0HnVUJTIziu#8(< z_tbI{-Nbyvgxs5rxPtKi5ChY}HEyUXca3{vsuM4Fg$RW0;RyTsL~EE&opHlBEH6pB z0DeffQ|&UUH8rJmhnlsEE8RYBmd(xvd%H-qxSi)5?z#Vo+GFbu1Nw^rH3V-q#OwL0s`mveTG-XJtZ5nlG=8m< zBl|xWPGkkDZg}MU@G`;`U5|rp%g}q9P4!t-4VnxYUe`1WU_5~U#sP|OYY1+!ws><8 zQ)68D@4Th<%fPDmSqyQ$hNp42*9M|cN{MLJcU{NZK?a*D8M)5TBSWUDRjvVms* zE1&%vsT>Vim03xev#YK=O+t?qk0X4pgG^fz&YF8e%)d~%>zKiYM0N@LAC`-6Wr`I` zG~OhN?QXwxc#%U|Q3TnX=;^g z;S(o_`aK;DG~jiqZi0F6f070>AUl_A$8XA#{{%*(H6wr!jbq=tnk4SK7h&-5u&@~t z7tc4n^(pp`p#9Wx1F|(umfat}e^JSjA&}{eL~RnUiCxRvtq`5sfx?E9&R=5(?teW{ zbCz=zzPVgHSRcI3-+Z8^uDEA1N1J19T~m=+7yL`OXQX?s9gTc!+q%lvc@YbS#JEx< zWPJ8HzDuMC=^EO235d-m!ZNoihc=!SCACR)M_UE$#9!G|bEqV=pY}90hCS1jOjkac zV~lotVQAyx2+U9X&xUP*9rO|j!6FeWgr|g%kumhRz+0~mlunO6=svNHR=9+jal(^I zXj6Kd66hFb43&lGSS8T<#Jx94g30H!4e{EtGx^F6-jL30Lqb`YkU2)e_PhA212vz) zl}o;8$cm4%Kij8!)oiwtJ6w1X3|JP9?~?}w}QjU z)<~KV`-#E;#Co{wOfudBBn`1Nv$t=^eY5EFtOhQ^^T-D_*ek^T05A^wqZ-e$_?f2m z2Z}H%X7er%pH11C%KMZoY1n#=jh8u_ItIG9Tdn;MTZkS?o#eju`Ed)IHsv?rUedd% z!}NmcaIyzmHii>x`rsE=dL~B%R|^Qz4BTC?D#PE z$6yXw!Cb|)z@mS{ST!@7y2=1F#a=Ib;$xK$PpEL9DjZUc&I^%j3eItLUT+D(;IOul z0vv0%0tbB@L|s^9OVHJTp6WD#K~d%3)@cfV9q4Wj^sf$Ck^8#Qef_xExOR{G+UUOK zxv%%#*E09@*e1sw;uKEeRkdvDMVG!1D7B)u($l2B;nHWh(*LussOuV!`F=}_BZ0{3 z3|sYjw;U^xE#2n^xA-N*t0A~@X(T86qSIkpIK7@jI`SmD4{%FgU7hW+8yiHL=#t-M zOu4;{Dn)e9df22>LEy>d{Ee31!s#>g+R=7UG{*0NXu;oo4tk$x|m9{(}r{Y9+g) z>P3av1vPYmsrL1Rw-U(wI+(WB#S4- zA;I`RNw=ek-2Y>lG~rJDfIcHBsHZ3S(!FkszMH<=lIt_!>JF_&Ye-(^5@!MujJn1i zDc1|NV_oufO7_t++(Dt_i7xpvC41M#$v3#7mp3^?n}R<8ffNL<{JU@tjP{Uf@tANkOzKXX z=e@rTU^-{rN*$VKq5KN=zMZms`%mE@u=F!YmpR~F)x=&kCsh{d3WZC3gK%-M6AnmkOr-N}VBrZ!L~^ z2E;lO8eX7O?N#(cc&|aJ4bp9l2EhTPeOcl zz)9U>$W+~ERp)Lm&n2(7@(sa9Kt(&~lSpF+y`=6SP3?Z_8@D98@y$?RmRE}2NctY7 zq#Iq}?kMeS(kI?bHKeo>12)kGtSBnuDDK*-xaGzd@b`232&iDo}r3_IOccW0v$}R5j}2Nkf(TyTefq4jWb8zWf4*VX9N0 zDc31fXBV$xrsoZf0eUoR04u4^1N3OtcF>zkjxg>WG4Zs>?_R_HBeS$vX1SfOt% zvJX>(vUNh6zfwUr8);w5p2=#ctLBrDMB}{qCh&=qHFa{+fw1_AkxJxl0KVM4N*fGY z)-Fg2FH{f#!D5bz5ec)F?Bo4|HX{_WjIzm+HzZ3R>iw|MJIrgHu^O9BH36J&m2kiN zY)#VuwCz^kv^`k5f-zS=VX;vc(ptL{rxwPy&y(D=DKE;(d0yF(qWAIZVxF+bW|)(;umD075+Ao}P}>7}4|j-D4m z;TD+d$dVX1{}0I~_lU)x0JhNU&`rDxc_!Cb-v^C@HAv(n2Tu*Vs57(4-@mLuj52Mb zmH_eRup*`9CYbSI*7wSYe0NYQm;97WhLZMYC;!7K;OianGngUF?w$*Xa27k9x?gz| zRZlq12GA`IdpL#~!B0!b-dozrCY?wZi~&;7G#JzTj^dKvB@b^V*~kS!_W|XMoCzSQpq~x z@Fc%mE>CA>ZB&g-8{q28&}8qRngY$07uOvyk+8S66kP=1&b`HLZ(jgIBlps$#A@`v zRja+!^CfPv5qu`;X$2&5&RZr;oKfjA>d9E$EaRZC0lH6sdySjrb+9}&zXO!80>#2g z&VE&DoPp0nN0>==OR=sK{x7EhPr*lA-{%zc+|@8Ryz=SA`9>4Yn9>VLb^`!kLFA#* zrX1+xgyO!wW>HFwJ5Y8j9%)Bc+ok)e63Ja^4^11yH5_Hq`OSEz-tqI201qtAf3?EI zT1%JeITnqP4}r5;x%3GWd$79uU>btms8@>#&D2raHfjg=sTr(Z+t>uBpU>ld#OdGZ zM{5WndG_=Pef6UCnasz0+5)Bd#oHev`i9Ok8o6tl1&)GAIh6plJk>J#LMoi>5LU&z z(c>sABTufXE#VkE&(eq*5y6aL!yq#Tu77itxE_V9GLYPD1q~fa$W>lPztPNq>#Yx3y8_e->LgG{s znr&sJm7uMxJm%z)A);mfjEU}Sh!S~3Wi1hvM2J2POGR#=?Gl+LisMJhek+~gCyD_l(s~67dJyT1INOYW{}3eVCeRtkR7k=wO0vtti%-l~*_r8c3rX}=u@f6gtLR$sE9KHlpb zXLTI89ZkBTuPNha$3=VgiE}Npz`r+02@;N-pNJ$OaY%C@?#VHrg8kF-<`8XCyGCeU znir!fY6-N76`0laU<{OOB2A;GXPi{LmZYJLSH%g5hg2@!oQ;I;7NwfdodPI*F)L2! z?-H($6Fir2X`IkW32jOTlTav9#UwXV$pg_DW2F>{e>+n0;g6MG<(Np93;7l4!nY)4 zOXixC;d)pVUS>cS>`N&`7KgR13V6D+$NPWOAb&OjfrnEwT?1&FF46E+N258e42n@Eu3X^Xte<~Dpg>O zB(ce$f9F=TDC-?=e~Q1yJ-VnpqcNEESV0Fs=%kGuwEWbJxD!}qYG#?tGkY-lGQQaskiy^D&an;$06riIisvgNqf zfl=xpPcDEokVLghX``7Y)2WS1JUUFwr+Cd%taJKMk5eZ3I9oV!C2JfwQf_~WZ{g3P zy~L559xdRAJxVcgV@GCs7iD!xEy&zT5D`6DhMb>x78|U}Ke8=tc-O3~)MCIyBQn$x zX>kVa^UAaE)G+H8m@f{?ez?mJCoTb1b!N5}CLzY(8CUE|_}!`Cz{99Ao4oPnQ1k{- zt~z56)wv7!>RGF_xPXt_T~H2u;F^p@_WQ=-!q~%CuHh zj0G*IS@_s`%$Agoxh19Q%`Yh{1nno@V?+U4%9kK7qBrhiN{9zqAP|2c~6IvO-nli%nrRB_KA z)kzSSc$dsjYAb#pkQe3{b$jYoE-d*@;_;%Q~k<`ytnxELs{(-C!RJvwQC#7c8A%avh}^)LBs)bvk`2;s`6!& z4{e}bD6pq1KnJt`D|DHe5^aXAhUWj#*@JmhX*HW)C>*|hHP88plMEG}dR6)O92>nu z#PJpmA(Ihv2njSlcsEL2xAX^T5Q2Miet^QlW4r5mi_Z|4(A{HDg(LG-x`%A%?&%)z z(>UT6UvFwsqGe-)sf?lUw~?`m{7wb6_OdWl0;k|oF#*3K@F zMD0QHx-MD+1qr=t!6TQ2pSTH4gBq7<*udcA-$8hT{X0SJ;+gAP0CK0g@`%@5xm@LQ{c%;+Z zu0NyuRm0AI6Kw{p>%qilbUt6k5kIk)wZ(+UNyL|?R!V+0w>({VBemKh@ddXY|MK^1n;8gwn;_nGY^%)#t=POtO)0=HS2E zFs3oD0)>E^mF8^^W|1bt0lS?p;BL=mcTa5)nY88;GdqgsW$h-TaUf|%KZC+)dz>3# z7bo7mSlma1EJ*K6idd+S?$@O%Q{^VL|3?KIEAl@atd1{ui#i%DPID$dR&C*+&;aV@ z22gWvx|9^Q;Uc3f(d!^kX2Q1!63H(1)ls7CC!W?o{S`;LFr*7L>u9X%ShIH89BMB{ zLI>5Q3-7SV(Eos$4=VKvmR6xHGW1!o$)3L^W-tW5T38Fmi^gvh*Dc>RB(}8{M<-C6 zBV9V7g(F?#hz@*TjculdovmnE1cuc$F>2t=KQ0nEGp$r;E||78XlFhowlSFefNHLW zmj_?pn;%fN)hVw8ft;(N$RDh4VpzEc21Lx_CJW(B8Hk5GUL;9Q{M6g5Rv`ZrSy1Mf zEUjK5sZZ)w4&6VnSYO3Y>yKZ);lkGLntC%eD_33AO4l);2oYEg+*PZt*yp}zEGz@s z>SB|rAn1wezLZjxH%uc#i#9hh3Ic#z9#EUOafl?&Pkc0745asT5}#WHQU~FjJkCGz zNYFMS#GL=8S~Jg^+NwmVoosLJ9i@jD#--%iXlw|^&N9u*ifAm&%O!uOg1qx?Lm}1g zRxW@8Lj-*+&?Yn94a~S$FDC5;qnq>4(B_sR6X@+0OA*nSOD-_-y}1WKQ;Xqdq7p7M z&=zj#pr^%WYmzCMysw&*trP0}YC|T6ZD2{F=%J$wf8yB+@H?{~p6%4xzK9zEB-Kt| zeqypq)HvenRacyv7~ z`&wx}e`YIT#3P$cUj9sMiEdE=H>nEBvb*QA*OTo=b54esKVOt1DDwUKMhqU?$iG`M znNV|pQpJFyLvmP_}K9ZXbg!?nV6K*fEZd6ls7?2_bz_$Sm9U;55gZ>7CD5UK1yVX>DW$~!w zypqPTy!gbS?oS2uEd!)fB!}PP3(-komFWKnKPth+@p_l$>!_j*6o4_@yUvhD+ROLe zKG)<2)`$Vp=Kf-F#5y=+*GzHKRH3FAgR#NFL+|NcGmFS9x%PJMZ;O|=rV;Ri?MFkn zr5<#V&QO0u3ZkU09fg{9@Agh3t{ioyGjwTeSEypd_v8=s2%Q-wsX1CFaSpm%h?9T4 z$-4aVh0aH8U46z~rW>Q1;{iSweGzi|XfnkK|8b`S)fu%mzlRK=7TDzKI?~o;$@!Qz zk~6P8l~!lH1hv^p$Ey46Z-$ZV_pGtS{Q-w$Gq0mb!mtueGU^=itRt)j3dIh64!sz)Y2l=I$mbhds1!LaNQZLQ=B?U400;l6oa2Sk1yvw zGM@QagDNzoI@4&hwB+-6zxxKbD|uuz8V0RQyR?GpaB@6d(6NbRYR9ciWyt1|AOBek z3AtrN>!>NQ%u1Kh$XEAOBbzTI?x##a0L@LSe1$@Tb2GeEZ>j6wy^m0cGrPi z)qAvbKfe8;VV~kSIEbX7jkDr}L_1Td1sf7S%IMLC#Kb(%+e(W!01&2ES|+^QJfThM znF!4hF`DG{q=}wa?ubY%9!=8F#twOyTSJ(K^Dq+(W@DHTZ9iN@s@r~8OAb1_XPnUB z63XI)1ukK)IAOL+*ey=D%_S7a36qr2rgSwnS>Xo7B_v0SkZ9j)t=sq7UM>fB=fwGC z`pF#geb7#LkQm)LfqgAPhiS&+{xyJ5L-(I0>0+D;+=goL9cBndj&X0QK`5-`I%VWH z&MuQd;(KN24u>IlhR&y#&o4kAjhaopM0{Ph?}KxuTmJDa@+G^6QVZ5^{yvI5NQkd+ zkE7v#B^qk@nNA{62*0_kViQ4eN>KYd<_;#eM=2!IFbTFbqP-`?wBOVK2J0LSQUM)g z5VZ7DxtSqR?`*h^Hs%tG+?R$k9DK@sRk*LurRtsctC=gy5EW{PHpaKmmDP!j&h_Cm z9xb-??KFm4eCb=2giYL+@@8~ELpT`=&YX!)43*N*lPntJCD+!f*uoAbE8!gJP2Wqr zDRgHw=SN+_8f4(y2Lndhy6TMPnxd$gx?djDvq=-lvRg5^oehdk4~t62bIuVhiXPmo zM4mpgW})yJg6i9BJ_MwnKs32odUw)IO?sE?BMvhK*%gF-`3l3qx3;FZ!;fZIq|hxi zmwPjX+pJBm9SB2gAKw~b+p>Rz&2Ta#xR_cMYbQ?xJtI)R__@=eG&^55cUo5zE?)?G z4!PSYnI|MV?v%^|bAaiT%=u+t4332(4s&B)piG+Qw^DmcI`>z|U4Mn#^;gKF^_U&K>*D!w1Yk9o!rF331;hX_s<61Ble~}6ZP$=Rk6reMZR~o(JH|E2I>m8 z&>zj%eNP_<~+1x#G0ua@w(loOYZVO&4|+etU`%;dBwDB)#E5_{-x@I|zS9_?cH%9E6W{ zG6#@Ji_*4}`F=3a$neJf!9+Nh>_E1J=~AU@viF|*y~!PM{->&>yFKj(esk{Zd0KF? zB@eK7Y&fw#U_&~aV4Dxn0RcbfnsaTymuYsU8S=pcGzfO)l1m)An#=_pxEVhy*e0%V z*S(DxTNq7HMShnIf80=#lYq_KX^ChvL zebZKP;xr?#X|JZJ(%HGDJ6z94Nv0r>NpIq)Y zrz+FF6QQ52U`=(WBCTP$YQoslk1P7KiL-Fi=>oxy-0@U~nfMUpwCUEbQyEg^esPM8 zW!}fZL(mGyRYI+}E?sxVNqzk(lYQjZm?<^}C9di>H847l**LXW)J>wGF{JO4GN zBJHQy@aDmw|4O!GYkcF*e_ie#Bnd`jRX@*U*a@m!`A?^WUdh5k_wSP^1r1!YL-)Km z?BcnrvR70XKWC^pla`moH|NtI7FU^|o`?k9tzQvbZY_sFVa?;BnhQ=z#v*<$nFS&~ z!peFdGf>6RWEZm4QNGem#6R346!D#{q!aPo_#KM)1&yE-q@tHs&;t%p?D-plap^8NO68rpZ5w9jcFXBh>B@tid|C)#okwy@2 zPX#Oz>(N(Zp4@HY4=Lh~$5uvFLvW^WasTaLlWI;#Z!OiU3Z%Lb$5|}ZoC~2?DAFd# z??Vx?`J}K#f{X<7swVf&7Sw(%0P3m@H(KpYC-E6QE)`wg(wErD#C6miKC*O=e0GJ8 zOAWTlL#Ib@4pp-b?qOBKNy195EVC(@25&&VhHO1Nq*X8IU<$YS13hQlkk`(renrJovQ zi0Cyf8G;w#zQ(yfs0@&gcejQ(?4~FFKjPj5KFaF){~v@=L@{o$Zs>?aPzkG}ppGRZ zfr%yr6L7~El7U3BU^2s^Qn3Lwj$^gfR;{+Q)z+`wu&oxY3oaF0zICblhPH|msk?%E ze(%q@&ofI1*5CjCdj0=Vp1IGx=bn4+z2}~D?zzk3T@+lUnk2)UQE~9xScd{}nVQMj z`|w*%^JNZo^|}1_Be4fuxhvVWA=NaF9MHd6Jnt7MzZtx_#@)9 zmo_LPjqlN$`KU`2g14M#(1@e872O&npD{?tceJb1>133^v4!uy(B@p58ttxH1;pw- z08AC`_#5Z4^tQ-f0gS04{}QU#9ljTV_AdhXOuC0P#C7Sp1}$d!A?bH;O1(GQtIxz< z^=px}jH?&$qS|!kC@WlM!`HO-p2t<$IYM7kQpYd81O2D{2Kcu3;JU~g+h~< z@S{K*zp?-lTZL2@?h}cH4ktfdHTm6wl{-R-yDkE6VdP#zr>~2@Ia5N--z^l$MciSC z?E@{{OfMe=(l&&x(&$MB8*GY9&!&RoZlYP-wFeN1Q-vZf1KeZrw=fkQu59d|D(F6!yNEv69Sm#C!Pj^p! zcrqOgJ*J<&sgK)PwAFA)ph!7`G^<0XW%lZr!MBx+92 z0TAFKg8xHAj&o&TcD@fO58kcH~10jMV#R)@0Gl?h91r16}0- z`RDq`TU01&ypk|`d_j17)8^+kG@6>9o*>0L=R z$rWC{FAbe6x^{-OvD6XCAJB-7pO@~cen41$?j=1-k{bdu$jKP2{#9oCMFobv&rkij~H%-)EOWeR+!zzY2OmtKK3;HO!EZrk1) zRT`x3VEQf8RDGPOzg8sm4Y*`5445zaG&*kMU5$aI@*lNNGJF*!(I_hf=p6%-lb!G0 zTg-;^3=x%@y_P)P52b6quUwI5G*L;0kE05Ah8SpGi`@uLpi3mjOY)iq6B1}uH*+RXy& z%=NEn>XKUEnkFjy{LWC*{cd_WIK?;YLO%~$PnEoPccNZzDY~ht(k!oy=@p9MyIrn6 zmkUF(Xv+zzkJuA*1i(E4c&6fqvlHWR{J#L`jcOi__`4IS=`v8er%1zM@NY)_8?U)s zX-xu$%KXY{WdB&t`Dk_wrv$nBHVgN=={WDXj?{neBn}u>380jhG*;AE1x__yOMl65 z;k@E5Y8IPby`m9!fmq1q0zWTQ3bx?COtNCkaOgL(BPfkZOc!Uzgf~-3p(uRicw^J_ zF&P~Hwj`bQrQz-&*%}VV4vpxGD4=fb^YTu-jU3X>`OH=AE4WK4i(L zswX2KIAP~Q_-zyPvsWR@)g^E#=ME^mw=n7v^=p7##l9A-*44R>re!4EsIEvBEprJ}kb_a`tfveM=ZIrC=nTnRAdzlLyv-7& z1zW8rnQyS#H(5B6MN04YHm64{DgMF$%247 zcB&i{yU3y1JrzG;hx%)=WHZf^9QGzz&Fkp%mCEoo=ere7&#@TVAl@;{j^!;1{rX)UFq+3!$wVDc|mSWH2@<7q^!& zX3H%I!)s-Mm36hyPrfJ8xMYj_tA_}QcQf1t#M4IRNzuI5Ea|fy@HGJMmJ3{Cz}Sqx zUxG%-&vT^9vx+<`2j>)UfaPJX68;C#xt%u1a!5N2QifFFS3h;@qRVd1TneYYg8CPh zSoJCeiR0MfP86eCRXb|C=NVIS2&UQwn7nR&#% zKsgCwgp@Dmuy2Swk6A<6Ji)Q0RZ0^J;Cha{YGkbj0 zd@o_x5P1VoV6YveGgae)J8t`$Bc4}6|WxTX($wToT_{Li+h#qL`es z&8cjTiM=wf!HFiAa@I+QD?(QKspokp21d3gEk+E$3zu-Z7&G;0Zo(GT5WI z?4s(x$n!qX4jzzii{GmRv$Wpo9Wfv)qf$*5whsg0VIOjCc zZ9gHkp!{Q2U@s-e%{5p2*&Q5*2=A0~zQNZMr$xnr+0MK0Kg_GC>Sju~%u0|dljX+X zUqfY1mRXYwkD@X(`H6sdmHwT2CmFuj`qM7FtK^F_X5?FcTxPw;NR5neC~g|y+Jo=w z5V9c+AiE^F*VvHoJ(G;>K7-u!X4T4f3Ra-xC@ENo;UDc@IaBVDWbk4L;_VdowvQoL zd6s+Ya&JxU?dt6ea-n;>z`aR?gXL7~_44Hew>N~`%b5)R8CHy<#Sn=Lr>MWRDN5yf zRljwyv5)o3ZAL+=aEHa#G9@;)_Kr;{BLBPmt5?~e@_XVl67X>`}> z%A|b@MIMUG7YHk?oO1M(2yj}*+IE~r0EeC3J`sn4meNG9^$eQ{`wr7!`%fEsTXV z6vcSb#W*YOBnSMQiX^U9(|w)3;17057z}nWU>YIWBlMhuJdUi$VJfKJ^D0uk$Xb|+ zQ<47w0)_hWDLWljwrb@y8NOUhl$^7ky7d;`0SHlk6Hb7@4Y73ejd*mN_I0G z-F^SpD*QRVe{NLhYS{w`nWbo_>XYF*XX%)zu^qu8e~1Awvp>Upsy&b8BWG@pLl`;q z1(^6QRKzN)nS?tm`GuK*w)Po?g7imZm$c1%i-i6g7!-J{)~MtBONaINUzFZ;>`rt5 z^33f3|DAQfQ1h$lh&}uCX+MU>cgSlR6_sl;tVKxdMhjVUr%-_33nbG5n~%0$_>Rm1 z#EI^j;Ja3>Yjk@%8LBNqY^`%7a2qdZDJCGA=-*wyE=ia?hR**psBEgo&FdzB=CG4p zx+T6R9+in;+tIKwb6*Ik?sM@Ic11zh4EJP9=#9s*37T9U`!y0*K_~vWVJ*10tdkT z$M!z#IeyIGKt_5Ok|5&N!e;qXKe|5nus9%m>3aPPeVLy->(%wUwksmC(c;4kT=El2 zo~z^!+HyF_fA zp*7|-J%PC{Zh`Jn_zb(=CeLs-u9sazkru#{!?u9TuNUVWe9`D`Fw3lmvo-~A_-tpL z{Fyw~{N{9+qsZKA>9b3KT&3Szc!S98@2>letzN}5#n83$Gq^|fMQWZHgnlI;CYr)8 znpwe&i7R#wP%+pm5(Qny4h-nHU-)4M!1^z#3~MdR_ZAHlXex5?I`vEV#fS7W^sl_# z$?9+*eU?v`zue`?%AG;&$;zd|n;dq_QKo1a2iw!4j;0x(T1ha-%C+$-q}D5pEQuI2 z?9q%-jN7hd0^wrGv&oN%FcuN^M@9w&uSQK+b*f3y0Q)`MfvMPYACz%3SC4w!1Xil> z`jm&}U_(=|;x2IjdK?yJ1apBxIT4Bq>-*^AAGXhJepsce3*TotD)ciPdK<8XA6cY1 zSGg%KxIct@_5A?C+5hil+Q%~CIAF{2Ux{OcC-x)5Cj2;Fh7jWqQP2HvmIpa=IRR5m zD=pB+G1XH-qg!$t$vs0bQSzjvx#5z*U&u46-i^m;+4Fc~!>?Sm?_+KPqI>ChnI3qNxSv0aQcJLJN-q7W@X}mdwI8p|QP8 zQQ=JvJw`SY=2tYiGv8pW!b%-FVLC49S|k%;`I0?~3k| zLVOn(Pxds)mEVw&K9D*t=lIt5#;MhvGh6Qc&FM?e1_hr2mSE!J8T~wFfNv(<84X&1 z?->ABM3a12eg_&%?U7CEEjk|*#xjzB9|;*0wG*jcK{~r18t#1)Td!qcF&Yf^nEwJR z`IW0s_7Kh8k6R-TodMOJLOFecT0xpWZ;wQdLa8^8>$Vlj-A$^eDU@G>Y+DM20k_WN zTs8fruQMO3tqXf1T#(9h$e5|3-yCNV={3i;+hO9ifU*tX?hR*D6ad@zI4OeqJb3+B zNUKVYkczDs-*1axMv&Q5>;>kP&1(_9e@r%;*W0d6m=AB>N(tXP>TTkeHA-$Xd&U#D(VLox#c} z*VrSOQ`Ads;9t08`-}!bGkh=`Y~llNQ|OtQS99l0_g=HEm9GCZWqNnKC^3^s%GiV- z?%P!B>Wc0v7MohxxcFd{)(wP0JoGW5l84IomL*!Sf-N63ZTNQC(b~T8zhl7#YhZ~6 z55mT&z|SXP#_M59O5I@2jqZWMhY@BQxIPtgMQZvFTyB9EyL3)L9$|6I` z$r8Ihrb5ftlwG<+J16-X=R6=b&4-Y8kWHo$%akV>`NU>e;b-4h*@gG6k||Cy;u{h0CL~O7?q474jMYI$kejc?#}(XMiDYB4U}i@!lt@H zoo>qYwhDJ9(_zZQy4fgxy^H#_JMwEj2@rxW{wX8C-AuC(VtNbDH5%5XpI5DI;vDBn zbGA`JS1p&Q^UYYkOnONPd}2E&dy7sXhY1A}`QFA$%u3{YIZ2Y_{&&y^Thnhy|DeGX z3ry>sN$;~2%9oyB75n@>&NaaqWK0Tm# z#YYIXBdt1~t3yf^PESQX?J|#L!}VYH>PDN*fUzJHS9xv{9eav;7Y`_C)Nwx&8I5p%wc|=FL-yT1@2Yfjz?o-M4g<-V zb|5Od6YI_R3V(rVu7RhuW9*U_C=0>)$>Bo#UPbr+B0kLqLHh<56B|wL3R1=?Zn^M1 zA7JRpf`T0GfAmOQ`BH+hKJ3=-t9%C6YReWr)#$+{!!0=UOH2;T;+^@<`pzmM*}7h) zUNSrpCuvn)pnn zoOBDFogVYC{Dte%ClIApr>3;VTZb7ds9Xm2xo_bE1ZJcM!#$^TiIHc`P~gz{^oFlg zYN~MVg&q>WAKt20vCJ6EE0GK@-68-p2sa4-I?~k})-07)1nX#UHuqm!R$M{Oc+F`T z5YP&Pb3BV*o|RRXe1BerB*Q^!WYyvRA6E=*lUCcL3a?%6)y8b+5-ZAW0@`q>D0G{E zZt~GOdxGy`kZ5|oH+?vHDCB(^lF7&i_7lDZYo7goK&b|Alik=ld>!%V_g_&exNUwk z-+KGaLSm{f)%Vqm1h=gjH!Rm3~9+UnxD zJ)f!bTAQo(4ef^XyfZTr+%uZA(9A&JFv<;d#>pqvR=tIPAxiby-6M&;I2F=Q$Q4@l zkRH_|@&ka3x5Iz8eDdY-E~&(R4>vr_1EXu?C3^~6$)TM!a(&cW5%jgUCfxtGJnSYn zcgTU33tJxCCG1yR=QvVL!fpE(tG?Xt1R=a~-|t9QffHRjkW>NDWZ|A4l0>7zFB6uJ zikqs3%}hg_K6CmwOvU>Y-qGK^g})Ilz87up>v{`+;vq;z-juWv$O;E?_s4ptu51!H zM^Tb=;Vm#C)i+)^-2q+?Aat5LENXyr)>d}MSb~tSU6;O&zCt9fC-;dC6o0S5txJE; zrD3E*f<|fh*|)`u0WbYb(l!2*#b1BqmGUn4-5g@1rKebKk##ezzdNI#~tK=dN8;cx#7ls$fW;J)KLmi*aQ0M%c z@FpWSyGmRsVs*i6Hy4Ih@lmF6hUM?&E8a;=(y_l(!S?lgwx!)Qz@(T%&WcX62Nl%aJZP*B4#y>2LM*pAT^F}14amW47g6+QFCD*xR*du%r z@f49sDkI5_&N5QQKXr$w(7-gjhgd4h0g+!jv?DG1hc0!nq17h^ZXO}5Y~x_LSBt)C zSNF5t;;7?FKxi7;FlUckPYDervj%(XF$9V1t+O*xL+>DJPS5W%5rwNgm}!})p*I*z zw-@2tWET_bOt1tg*i&uFx!Dn*k4c{CWv~f_zra-ghG?XZUOQL;Eim0f2vKTo0-O}# z1KfzW^^D8{)BhMyc7bWZX*tGPj<|CD53u^5Q)AAC`mISyTVG258yo5>awE&^aAm`G z8c~sP3`25LR?UG}H3wq%kjNs@fvmz_ zN_LgO`CwWR!MuVrPXTW@)u(2@S~yksyjVEnyjn}LFAmOBamny=2%>1JN{j^M++*?V z-{4EUrUffjP|&62&)w_ZOYYKd!HPnoK76tydM1zPZcy3D@b*IJz8vQfb$o`X@6)Uv zH9DYtm_v0eqtiTs9{j!rKWB{%b=h%0rL(L_&5HQq6mK8}e|nJh1T`|N5p~A$mfx;l zzizE!0wD64CUvZ9TG#ozC;kK?*L8n#UFwy=`XOR~w&&B&g9>QiiIiis$vFD+0NuNu zjIE{iYc>tx6e{9wyl%T;KePu(y8y}Px2J5f6(qN=j_)F)tZ-9EjOiUCPY!#UR|zAe zp`E{bzmNDEuiHI0tzzP!LMXU<-KHOEEZbh};82rUc46L&|1yT?1R-UrQ~q(XU&n{k z_9?r6*L4Aoad~#XeogU_#}~Ui$?)AwFM#lte86!jIQX1|bjWx|xrK)r+0KId_es8V z30`FK%gFgHU4X;kjRSp$L$EoU_^wM_=Owzjlw{K%QlDV2k?z%HyG&hvNE&tdqSPq$ zl0}22OrrBbaxq5il;CuaHdn$1SqbiX!A4g?dA5XAfI5yC=St9eJP5rKF3c(6z?>4^ zoSmutC0X=;X9QCFjR$0EzrYeR`=gSu2NlNG4ymXgJu$@1hN_3Up)oV(Or(dmF#kOAcz|_q*vEEJZ8t ze>0Qj>-3e1Nk;CHm6;4*EezN@!_-llwSbNQ;`1utaSI>J#_xlB3*P}iZ)BN(Y`>Gi z?=sL|FOY_E^f!Lr&#Rf${x&vs0b$L`a+I3C@p}&h2rYd+xolYEG>fql2~+m_jjNO7F;YpDk5smzvHti8ytpfpC&Hms`d zuhbI$9`23l-O26k;jZ3aHO)UGdJ8S#?cv^gq9wmi336ZEP@CDqeTWHk?cv6jzY;98 z<8`#7h%dZQ?+n!qz&kRJ61cY1;)Q6iRM&*P>1x4f_x3abW<}^W!d!a`43wWf#0MN^ zSU049apKm-)`kB;!%z}lpJ3O1qKX%sc%o{c)zxk3-VYomi_Z&bTlWD_|D~}W*7^hF zlK?Dygg{T}K=7d#QKy`DAV#|AZK>z(8^+;|yMyhCh`6kcF> ze?Q7Hx#=z6|En?d^Ti5%t{;d3NGtlPCVP{{IF+9AZZY#O)7e|l$>2jTtD*f%Klc{e z?v?H)o!}5^$eS)91M*{+X15I_gWq#+gB_M}@Eef3@;3e@t}j?+SyEO;?j;*PqYFsB zhUCiRi0A1(HXKcIIL_Z!IBs}CS-aV)?|p{;QL?y+8rLp~FguuGbN|)C*8PBOb9(n2 z<$g7N4Gtq12YQb+e75J`tn=UrrrPa>4_B}%#(qLKcp40u-8ke@RZ*7|H4-!p^{92x z<6REjD`aAWn;OK#`x>;nOu=rb?)|5}U#k7mEgPilFVj9*K~HL))aCSe7}>7nL8tlJCflsFVRk^ ztHpR8|MV7aM@jUaGU3rKSotQW=^)^Xy@}4=PvmY8c6*rvaE-R%u6H0}Q7B9rXKyOw zJZlIxE@cRS=0;%5K2YO)Rc$pSwb<-Uo5qqee7Ql%)-cI0PaFH841MtJ?+8)$UPuku ztXt=S^ovzafk^{>6!i}+geXcYVMqrI`QD-^i+y-8iV>k4DleciwC}Va9?*y z2G8;+K}4V+{-w9fazZjP!Hmjq>GM|a-;t{R3m>C*t#vwM?s{1=$#4||$n|>946(5_ zzq?##t@>^2OSWJOS?#O~zW|2*2fy40aAEeg=gG7cTlm#OhyY>E-k}&$WHNa8i=xln zs+J7iV3OCry>zkI#ogHMuFtXInate#yR*k2=?CcpM)rCNU|UWa{W==y4zc0q=zjJy z?@y{LYq4c=kqKy@y{n1@5TNkzj2{Y2gF zCrKo5&PYJ1t0mw195uNTCFvbCIe4@RoXUcZcYpY4ArJ@Q2V;HkgqLGoT8*r6)>kU8 z{4ODrx*Ke!qbf7JW>ci312b_OWg-@?3*NS;=-u|9xry~#4Tos=`%%7g4D!Q`Pw!`_ zd_Z1HV=0B#&oi&K#`f>bYj6o7wcwr{lW;x}m*gB-t(MHq-2s1`31PO$2dR{mF)%Wm zxbz(-sFLidKZ$@VJUAdPw{Ku>(l9dv^FHO_I~pz`eS}^I4tt5$Tzm7U9zqRk;gEZy z9iFG>22&Ng>W`8=PCOlG+2P4xau3nYhiMCUix5f;J&d1{HGu(v!P=qlTGa0qeOJ`= zmUAtp?;y#TW(_E03z;9YbVi7bR3=`O{9Eh_i z_Gu!B!LkM%@PiI9TPZab?=BVDJJYQoFHu4&^8K5DPld0upP{ewb7vTKO#hg|)Y4gb zXQx-4XE*2*h9}Iv1#+zB6mAKp`Ja%wr=!BQxBf%i&Ap1xs8x&pw7Y8Ugw@bFCIK?N&-V~^ zQ;f7Hf*@a8UX)6j^C&tojvUf8Suz40ye>9zTtV}1tB&6*RA+IS^YtI)O`air(DSo0jBmLrD{vEyl{;YBzzukouSZ0-HbG@mlg? zGHHC|w&dZE>b2zhf__`_oV=F&+ep798$xV#bS*gs#JMebfW7-Ix#zS@OMXQWu8JXR zL$4(jl|S9+JA$IN!p%m8WVrcBaon#&EW>tyx=AZ(%ou;JI3}w@D^l!-!kp+?4((OR zc_G+*$OaOV;Uu{c@Qr|)co&YlArL>3Lg7RIy<@ZU@~pSGDG5^Au<+pw<=}o z<8@1vqa9&KLHihGC{9iLc(T(fd` zN*r#aak$V(YP0qN{Abzd~cdhD+<}FOkE(rDj`m^HtH@NSCw4Ec!nrP zzDlEVljvT{*nbyNnzN70aX-EieQft9V&P-Qn)C?&(^ zyJ?Z3V(DLF7jxP+Bb@_2AkNi~wyaJA&qzX`|v*2)(N{>Ee5TkMff$tUF5- z7Oe+@ZC1<#w9U#Bg!_1Sx&IZzkRm;iB)R_^q0|N?+!QD8N?K+!P0?i}X(YJI=oY!l z=;rinILAbtT^HH%?3zrEpqhc_(!BS7l>N=>EZ8Y`)R)7wxu_p!jz z91UnjZ>|K#)_U_kO{bjRyho;MzTQ01D>oVbA4|;Y&DVDzpO}AZz4<*uX?pWKXAR#7 zu+y8vVIfa%&L_=dm$zv=F{{&?M_PWahaUdZ%H@LaSpyHBx5Y7s`Z`}E?ciSisUKcxyeqTcS9 z^Y2{z>=@%9$%V@R^Q7&z)HciOS6<#rzOCiu zj*9(8d3ooZ?omVl3zJ6=EkPvqr3WZX(#?r-dey!`hdD>z+p zY<3)OP@E?(H!Dw z`yd+A6YTF$L_dOEQQOeRTH2$vS!n_k#VNx_L##`uDaBeie93y% zqp&2ZhQ_j_!3^Rd(V=}7;dx}UCVaLcIm__v3_fRxs03{5$`MGP@Gy&JF5uc)^WU7k zfZ4W|49hXAb}_QPg_xLrR6k;3{Q$p_{;QZcrIJ~neMJs`%bfLCbXSqtcv0KnsJ_fP zTmt?UnW2Z9dfR!YXm`~U7+nwIh@#Ig!RUf)TJ~BgvE+WWPYKMYT0`lm;# z86$JuD|5-g)~=CLGZ9-H#H38bMnw!9b|4YCzRbso_Uq>>96DE@z+&N#ucWaJhW(0A z>7<$%$a%)aQb-=QRmhP%@_*G2TId`!qI~?r-c}eq?iJn7bN=~jn|XfDkIU_}3O!6U z>EWD3?Ce1D$vNf2g5AnFiTe*oV%IcVK6XWR-fp;X=-}+Q1Vk2CE8&U&#RQSFth;;_ z1zF$$Ba=Rdg(W2fcJHyM|f9ms%w4TDF?t2QIia5Z|As8uXY7`V{Kc*sw^>UfWyvIA`5S zd*5_qZrUZig?}cEWkuGB6Jwxb1iZ?Uon;T7{D3UmE0r5gfA0wWYPGtzFy%1*T3X&l z-}9D5ha~4JscYG)K)jGLFY_Uivsba-+hw~T8_B-O@h-9>8_Deu`@6_kHga`u;SMhH z6fctV-d_d+^H_%BE2&lM=M{`uUvN>;0M#|}CG9}*Z{DXGJPw#@Q0!_z{4k-=6z4A_ zeOPcx`Fi66i@H_N$;h1!!xz{Kpf6wFTX>0wX5&Pm(+I^;wmP;>Mq`3KPXge zN7N?1{2sa1Mnz(|J`p?nkIWI9@uvYs9!X3D}0g{-5S!tyw5851QDBdqZOtb z-Q28E_yE(wuncQ42boz=B!%xmVY(uzKP zCNwXVbz*vR&W4_l|b}gR8GXuD-t!CMZ|mv%AS2tiaXxU`6+d zA-L)Ox1PO-6>S&TPZOJ90*#ATf8r#lEsVByd0Rj~%xldANdD6Bq z$TxMC@Al|vqSGY6Gl#}LDOSXW^hf-`iMHe)zH9ce^Q>(Rm`Hv+z>F1R0%$*RU!fdK2yp??nSh zNSPpdoeNlc3nz*UoxDpg>Xcx8<$r@tDMk^ZXZ z*Y(#*3`VU4Oc`A8qbYlP0PZsw_Vc3DfSMTEQlGl_I_hnMH9QXUNU}yQ zfU55Idkg22rR>|NWKT@T^u9c%<cocZlo4ACtxG`hzTNE?H^0*kh&@%H{-?akXM zclK@eW}9D2RmYw``|&CW^{hpCQk&brC%_OU9k3C+msb{m51Rtec9 zb=K38nipVn10}MpvNuG9UK>vAdzaaZD1L~o%!wcNehDIeHdPXTLCS5aiPwO?`gi_3@K-ciD6^IQ_5mS*25jsXYY#jLtbGi_iMd!~lh;@ytoewHPG@ zSFbBr`5SUCzgsMTDSsU=sOo}4SFQ$-pH=SX3iq?za%0|o2ZY{cA#d}PJU-rcPxHS( zsr&BjmaD^zOxsq;mz`j*;V_BYB_;I!XPva^Gkp`9i|tXD5I-Y1BJJ&(!j7{Yt`~kF zdoqz=`%=~9Pde_&Y+F*^e#z)9tRj!2B(Z|sNa|gf_b6g%pDFzGTq)_2*(#-Gw1#>H zzHqI$FHoD#L!45C*oXXE-Z$p=y3_TecqzM`{utH7<}8%+yn!Q#^Eyi_u*@@!XFSsE zn_UXIqDdQA@$Vq)dNh1eh2O_Uffrfl zF@)hEHUfB`%sXwe30Pyt-om4ZDQ5!hkU;Sv$|Bp0{n*%MB3*;pLct5)6M^0bG_iQL z{($BkhhXrYU6f;UcpKQ4n4)?D1m?+#+>Utx#q$}el)8#|6~P$$0u0bdTIp)Z6y1($ z#hbOV1yzg!9H$@KhpsH^Eere@c|I?GHStk9tHP4bO7;RJm}V?nUvT+q2Bn?om_)f) z_nP1buXi$}NxjK;kFCu#r49bp)a=TIF5zw`zLvPRKmJioZC~fO@m32iCr7=@jO(fD z33y(Owu~wFZH8ODZ#CV`k!?(rSR+L?%7(BE|G}C*{fVr4smy}xu(yFQ7z(qIKb+=8 z#)q5FLWgh8Bd-r3`SpwteqSS!4Y1vFFOQ-N=s4Qm^4Ud>XibvL;NJrG z@A$40{awqR2qX^Iy+wzJzJp}xGgV|d#`(fw|9nSSUJ=gZoGW^sbM;?K{&W7IZiCx~ z{V@x}<*M9|Sg_(M!O86_9|n4ZcD&Z09*iGkk~Oj1Xp!>`-OUY^1S}A#0fupaI{jxY8UGb`(S1Ic9)qkvk z8ObnE^q4uT3NG6X>9y%Zrgobq(uAA~1q5zax^0LJKTL!MpRA$qUA&OnTpv#WLl%hz z?N5eXIi^`~**u2$CT^#zdSX*hJKZ>ov^k1#0b3;+XnBrduGaNyi8D<|g?IbCd=Isv zjC*0knr!tt)a=2GV<`Nf4J%|F2c)U5FFmHbJ#^ zvJI8YScqlXDrwO5;F9drt>+I+er4fgZ2QQCo9N=i&PyyPss({F*g=^-%Xi=|ddKTZQsWA7x}; zavEoSoi53uT+s*R*Xb86hfv0{DE}EUDqDqeCm&_eNLt!ZZcM)mfJf!zJ}5bNlR+8J zqFnA!jugr@q8QO;jGz8x7T259G{45jWN;mw#dU)JlJzD~bq zpsH#hiz|H~v?PO%_Q*lCYw)~Bt*Y=q{ zSudx|A?=OHCgnf4kepzVIG`9<%zN$2IdzGCGzlYL*_0#t%TNYjyObh;^4E(FM z&J|wg!T&(;9`c(!;8P74Rv31NfK!o?%OLwF790G7i<+x$SmC06<)Y3~)HyEd8W(kv zqO65o+ciSzY*TL=(uI`FXSVmCf-LFzG@R+t@C>Q0g0qE+`v|;juMW!++~on^46vz- z@HkiQ=OTEcp>Wr_KB#t1hVOHuC4DVODElY-<&}MrU;j+mJ+=xG?l8r>Aw5^wvb5gp z!5^A|zt6#6hh$T)PRNIU%!B`oXjivu9ej<4e>)|3oiTV90j*0vMx3i#9AMwCVf(e* z>P1)NLmbxu?u1E2dd{WZ?;85xE5u$J+yUo0CouOF?+|e({4LUKYBr~*MQ^F#gJgq^ z{{{eWqYWf@n|r(8rTx*p9qQ8lhqs4nC%)~}R(Sdxwtve;dF*&7-^qXZ(B+G9uNevoAfvb~)ECTgM zP3(zQWU^{)a{mF*fpgZBU}KwkUvb|?fXkQLC4TIjEMV}{cSFmyaeN)0H|uz1)1D5X zY#jbPE01HHua~D9M+~T(9J^w1lA8^$iFVyTGkVO`s!hT7!)5^|)+eXYx)^2FAiZnL zl8MX8Ccj^>@&&A+e3QUG(0Lf*0M7jFzq1B{{2h;1bTcbrM@e`x!nn6ENqXhvPwghs zf}3q%pso9)f~UE(*Iilx))e_(a&ITN zv}fE~(4{@@-b!5B!|v^)ftK$9_cqa`-R<6bT-smV+o3M)R`<5SrTx~u6}hyV+}pb@ z?dR_85SMnXdwavBUFF`2U0TY$d9+;Y-oh^JLigs;avpCF1<&U>py!7$SB`NB=Tvlm z%prsEFX{N{1l>DRjATl`vbU;;Gizgd)OQp#TVhuUE%_EcOs@yPzIKhZOybKeZ1B4rTEy2 zyE3hmWMAw-ugRsVRvM}1XdtuSvN~GM_E;^x=PVyt@4V=>+Uu1F>z-RoxNp5N|~u@6SLv?4DJ=zU$x9$pM~4(BB#Ta&|jUvX1s_pTKoo%+$a z(bt3+z*n4)wX%XjrNo zWSfJ0+@_9ZKCx`VvKK|bjqzjTm~I><8|WRZjXnS=bRgM7 z{Cs>j8TI3LgXooO6Yq{+yJ@@C0}5_m>zLRiesAFft#jyz<(EtX#KgUYBmJlzFG{Q_ zV})gzJxIeZFN<~0GFUbF-Sh)MRdg|odml}_CkxhA((;#Lv0G!hki?p z`)`GDdOpVIoq5LhA71zd8a+L#`SK$+Cv&ytOait3O52!FLwi%@ZimjVX>ZYT(E4xL zdV3ovStp}C(f(fv^Fkl9J~1wbq&6Ph>><~^6r&w-*EPP5?JXKc5&3cX1-X+#Y{pW@ z;rbY6D?s5z*GeQsHast9p4QD=-0-%GE+(3A$W57WrG%>_@CpsSu> zB`(!{f%nSEo8oMV*uX5y+e(5XlPg?kGnJgU9i_2G7Z2g>dqV3Fks%b}@uPjYhTdss zClNSM(6rGcb;TSzJ;V9O=iFGy7)(+BV@>)%N;Rqe`eMf9sYvcW!gi=NbjHk!3ZP4^v_#h`Ot2_wrTI7ESPoou*9PVO8=Jjw-=fw{WD%Fk_mPj_PTxN>42nxw-^@0w&$LK zv!uM&;BsRPP76wRi~fp(*jVxVQ!K>xr7h`^mT_&>j_e4o+;KrDdXI06R2;l0)O8#; zscup0EW$%;C@YfX;}C3B-47M4m_kWq$r*#nld(Z%$x{YZX(QiT6iB1lJaSSAt0YJu@3y zOVD`M9F*_;iV>9J3;+bBhCZ~wGN%(m^xK>M2!kY=42JM?_zP?-@O-+}*Pk9p4<(0m zQ)axOjMxJO9bcs10}BkdximB&F|uUyG=6BiUi&*lzGV0Hvu-Z~F<`M&nX zb})^2yM*QS^aLaEgizP(11ff`3US@E3s%yVc{ojOIwu)^+e0-rPEuYJ@a<@ECd%6z zg?o@6v|y zz6vIf(xKl9=|5Sm>PzX4eUSbli*yZx`oCBIqP|E?CZumQ;hJrM!?SqL`c`<4^zil; z9zjT3v$3bng<8*^BGO8-__abXHX!1 z6kfHGsYy9%BIZa$HWG8JXW%Khe3Ss zVog>&PYYd0PPQv;JtTb7QRP=8*{?^1Mn+L|@q^gffbSF?YPju8ewU%FyT7pEyic@i?I^!* z{l@RP9QV99wzlzbjHRc8K1q=2DHL2R$Agu+DK_3_ykj!qD@~ltIi1sr^T0 z6l?^D6V{cDoI*~<{_}nroWA|6YURTPEAAzJ{8LrkkKl0by}z>i$;v|?uIRnL& z>x%TdLDjHe<;4aZX=QyjeLHd3z|B-&rrB=ed(-EbKt=#ZYKa~Hl(wmTovtTVKA)9u zB#vb7MIPd-4RL%bV~_Nzf-?5mMD|iq< zhl6a+^OF9P1(#~v0pEN0hDJIBi3Yc9NFU;gJ0O}`MqkXvRj)y?G5sUbbq8GnrrgAW zO>hjkF#FcCOhA@EMQZx?ypqTAttB6=y)k`;moFmIAi3;$n$Esqvpw09KO z9#+zI{}W{co*;N&Wm1_t9*bU6F#w1iAn@n+5mWHvwW0MmLDxE7aeEju3Va_m-qna( zL^eayB*L7Ym!Xu=Bq^7}VKyU^B@z?7ylXc?bo7|u7PzKh#ZP#-C&0KC$~%>!Ho8y& zzCV2(ei@ogiG1&hy2*A<%^M&~dpyM<9i-Rh1G^en{FKcAm8|jdFxPWmJA{j_&?W-D zTa~npF@!EAgAa*}(L#Z?a@ant^hGqS@6gK3Y#vD82Q61{FB*mP79DBNN%lP2p2ynr zID1a9=Tv)^*>jpbqxL-Bo|X2TVb7WNtg+`Td!A&^Q|x(~J`oWv%{WodoHr)5__I&&-3m1J$o*<=lAWo!k${G>Mgp&o|oG5GJC3D zdW){G=MU}qBYXbXp4Zs(I(uGk&!5?Il|6rH&l~OeYkS^o&s*&IJA3}Yo~!NoCwu>EpSI_-_I%!+FWU2E zd%kMV*X;Q(d%j`MjrL62^KElkaby+uR$y`rg$LEN(uiPm(LLN6=yONE|N=nMu_&w7Ox zDRhrQmn-xag|1iV7KPR;v`V3WDfDB7?m}|(T&B>|3VmN8Eh_aaQAlQgPn$xTu=F%4 zG) zwL*Mfrnl)Y3Ta`h=@Esr7q;mQg}$fIR|>@y+6$Y!=WK(+Y(?ROojKr4{hP zIM8#hLInyfREX^^fgWv-Ymy<^bB018bVN^$LQXL3LT-)uM|2=A=w5! zA%z}SXfK5}D73RepDMJSLf;Ypeadof6W>k@^t`LkNeaE8&~k-dROoVro>1uL3O%II z?-jaBp)KONKPeQ%uIRa0q5T#5nL-m4`jJAj6}nWR1qv-!s9T{$3jJK67KLt8Xs$vJ zDs+lM|5Rv(La!@SrqBlp9j(yU3XM}}7xDce3hk%R{tAs(Xm^FCC^T51vlROJ3qpTV z=wpQ*Qs`}kUR3Bcg@$PaJgd-Xg&tGr42AAjs9B*k3N@*J|DaGpp&J#tP@(G-dO@Kp z6#7`9ixe6mJ~&^Y2?}*6RH9ImLfSFbbEZOPDKtx=c7={tXuP;&ibACd9jQ>gLZcPB zQla4r{ZXO46?#yiT@>1=&>)2dh{HbroX`Y?-dE@t@y13%fk0_TeP>h4(s*-2=hRuX zv3R_>ZGLBYTjRp^=C*ilYRSxs{-R5(GO97+)IrZs3qW zBtW*>cn1UrW=$DBqqZs$ub|SiI$ifRn(Fg z%fG;)i4&%LcbxE*)yM0HPf`dZHL*^p>5L5@f23l{J387shEF&muxP?Kz#9zAMUI~k z=!nHTmR2^mHpc@s3PNJ2b7||`_Lfj$VM}{`V`y=6yeZU{Xq`(%+vkOpp*hxhbSOi` zB(MgW=o`^m6X;AVjCC}$)OSMr!Mr!dIvYBg7si|0+g#=STGxy&C2?+IepwDgXRNa` z1F05q@54veSTp#^w0M5kKy&f@SX->4KHlCjX34^a;svp#V;U8`us+@t_?8(u6AcZN z_-(-xiRQ-Q`i_RC=6I|jp6G}bx7IH#hNtR_TVieVzjd+O#uJ$CDy4oIKNFs#E=5y{ zi>8cepl*TE_O>{D*EzPfslFrDI87Y6xV>XR=h)Krj##aAWOGBk8ozATn0bEk*pp%% zYUa+dCH(<@1KKimn8VwdhcQ3l8!&up!rP;+OfxouH>OLODsQ2pHY4hfCG>^6-)WiSrUC4Dr5xecI% z8oa)3>EimOoqgfADkTSXX>GRA+dHPw3H1$4xlt!GoJ4M*e@N@bQu4$y0M(0O>(cgx zOLNAFuvD})()AfIb#wc-fHQQ{WAUl=ow1U}#tyN2|FjtQ72D5wyv*eo7XM`nHMtojh7o&+1wVJVIrz8 zbPYvh2^Y{ z&qhX&sU$~URCFGB#8hN&-`G zW9_L`)0*)-p?IcM)Rb1%mU%J0-pN3;)-TzLwLL)*m^IJj?>B*{1@k3*snctU&lQsW z0p+DjfI1*kY@;0>i(S}KAD`FW(b^x5OxpbRcKE7f;lhf>{@`+x=he^cXl|(PnBPC` zxyi_!sfo76mRSFwxyj9))0#UvVbu;SfLRUJ4Eb@Mu9jZ&TB)WoFjtmEro{!4qbm(b z9z5hh2V-_fvZrL?`(j~e*l{EI; z=7j-=tr)^EI*_%Uv5w*rRCzpbN^y?KS6mib6l-b6wkV#}z981tCl#BoxU{92Y{hhX ze$JevnwjgifhYD zYszQ!Nh&EVEw8ODo>hH9`HVnGBHq;A(R{9H?7-9*O1&dgG$n9ULo7UL?!?APjo~9E zPOh(?P(OLnyh#&}YMeCgh$F{Oo*RqJoj2~tBgW^N!66zxR8`-wl`+#w+}Qes&0`l$ z9P5vn&ap*P#!8pgVZkg!`E>>scC<@ko!%@p(>$*^)-fj&XM9+<$m!*5w8w4Pgj|fL zyG-cUdCl_^7;5N_IU=qu$Nr}H20uG#S$a;7(<1`UiHa?WH8@MUbI$2=@(BGVILVqm znC2lN=LE$20cTfDbEBk|-iUk5;u-KcJn6SEZ5Nnr*0QXI2IQ-3i>)KoAu{zy!eq!% z1A-m9X#7~O$;TGcJqy(%Zg7lkqp=pnR19%ERl6$JPo^R>vb{7vLFQpSy0OEzpZjKP zi^XLwx{)JU=~TqDlBqLtQIn zU23tZMNE?s<_=Q=UMR4*zN3v+J3167>ZEq=zabVH5@>0kU#Vg5&w?`V4ec%M9ZddY z$06gLgw2mEi?zgL?S<60q58Pl&Q`S4p*pBh5V25Wd#uyuY_TPnmwAv`L$M>)+P)~3 z!BsRR)R-_NRu5HZo3OIk1z-fl8Z$Wjc$*Ps1-(S3k~A{LI8`-fUUNrmF7{g9oQG*Z zOMAnDfD}txb7vC`(cD>XLxO74cBC2Z8b%4`{-RhVQNGr<&hnJ>9~MZ zs!wIneSuCP>2%;F9Ub*ceP;C%n%g?#^=%EYii{kB82-kMpD^)=@R3JNnp{7(p)ocu zP}ka2=R`uRt|?Xz(_wbBE;_1HKSv%Bb3ZO_K_Jn#psjszTcECPR{1Hj_(`-aZf~?wz3(F*ynSu9hlHrq19Dn4Q4NSUSePi+AUb{LJ z7Ap*XZ@6)8IFB_8Rr71)L<`dvrx`6`v@wqtY++zq@VG#S8MU*{`)=gK6PMXI^ zvo~vc!Fxusr^s_+Tp^lLED3n2xltNJd5PHwg=UIhZCc9AG_dFhxdcu$M}x=L&K2Rk zz$d=X0uM&UMRCM9WBD9qFa~8X#s*k%V|y!tY>YR>j}=Qw7t0!Ono_Ts=|4V-g)K`% zxJ(jsk>kp&EtOAJU|K!&H%c7%xJ`g}nrzRN(QOn#~Bb)PC-&uqG08w}%GjEM8iFedD#6z;(ol22z$t73BLZ0JH zf%&XvO3t-P#iWYy6FSa3PqW}U#7%2`TVtf6Vi^Nie9B14dNyp%0mCeaHI`}ilTS6? znLsO2s5Q}AUF#cH;>QZmdA^&i(jB(ivJI2to6CnCiM9a$qeMGptuia?AfI;HGGMa}BzZv*EEaGxhmj?K+@3Mb`g zulcdKucGku%}p>Rwy|KWrorxO$k6bjDZ~5A*x7t8ni788Miy~CCS~W?tcR!U%KWnpRy?<$w@M?VU>k`~;d8HsSYe?+i5S zpS^T424K&2bdP*g@kQB)_#&XZSVD^>Dzd5eO7!&7(z=;7xU+CXV_X?4lW>ayC%c$l=Iy?$Xk8i{e6sBZ~4cUfRov&nq#&HWggnzYIq8cx#W zq!$GaI&9?dQHLIL^pry)hmRON_PYn4J_oyO%F#vfgc)cVW38xjNMLv%gdq;G2_^FS&R}X zE+&vQsRR~^waI)9$q(SX(#8gIv|?b5Dw=X=K!eaiq4o}#IM&jbjmdfft$?9Jd~!9C z+dG?O039v1^+{FMh#GbZBmK8#Nv}Bp1pu ziWmH;aC<{M7BB9M<1lPBP@uEKQyrX`Se&Y6j#KmhwklhZ5J!_po;J5xp;ncwN?hE5 zW7``&Xh=t0j>>fD)*;#CMMr3zq2tU&lg_J~QES$W%n}(y6DI^*cV!HE$0|Noc;=F= zl=v1?Ce4|2*hqQ4A@f@V=C!x85MycWiTJ`q95$yR9lq+E7+(wKK{Ysmq~46qnl&?O zw&O`^Zw8skD#y}&6K%)_n)woFb#3UBKztD)i{p1;VlI6<1`mf@AXpUhqvo}1`N(vP z34<|9#MZV};T+ld6B08!W-wbpR7nyuesF0^=x2vVjP)6rLa~rXZ>N@O8ksdTAc>Y5 z3h8Y2)Wrj}3z}_)A1aZ6GQ0+m)gh=qiLO|vGcmWd*%o9BpNtJAQV0YU@8$zp`)yLd zCZ}T(ZB%+8vym(xHP9KFY54>x``AQh$5@8O*u_oF4NcfKat39ycoQxFi_bYHP~09U zZVXtlSrE(Oj2?7?5hk)GNEKu(Of&by7%Yc1V~|(0buOe;q*dDB{p_r;uCA)2w7T|` zZ2PEFGw9LU^~UH@fsPRC3R6vavr8A9sp{5gW>z_hF&CQ**-T9m5m8e0^`SAsIy&24 zqb1M0Yz8iW(k#>jW<%+$+Pboenn1;jY1K0;D{6^0omEqPe0k|COUg0|4hF4ng=B!b z<&=z8ESfT8RudF7n90HVWql~lx*+WY2P9&nL#_1-#1S1#dz)gRY34W$VHJhk`d-Kx zKMPq2jHxC9Vil03PSCmn83+3B{OGYA(-Ki)1KvWaRkcBr_P>Ur?P9RN~F8% zTqxApR4$x3p*^XZ>WIV?sHdW0n5@sfX09#`E8~vfY#o5lwwLonY((rjeJ&PgC}8pniYw!}34jCndVjv&$zL|`F{eURYPM~IfI@$%)$1Jiq<8IV6s zk}SY`GlCE6h{4b5c&t(7lrOsVu6ZzssXk{ zGfb|mxeis}onS%SG|xAUX4O@5GgeqtF+Z3%$ls*Fd}WMVrWw=RKDL9YEFSE@v>3*< z2<$_c&r)N?jLDfa%@g#tKuzG9L>?QkpPY=EENMizCf1xsZ!ke-b4VZH>DATKnQb6C z>MF|AJdPDZ9xtNcHN<>Y2A>tF?V;Hd5p`6;j8{0yT-xa}KZM|qK_SIzWF44jNb zr)F{4Km!&U)|49TTkG~e%wt_~X=rf=Mpb{1*!|h5v*dY8JFBetw%MLx4d5vU7G6Rp zuni+r;tNwR#`t3)TST1arB5FvIz^!xayUFR+|v_CK+(B`gyzoCq518!9+c;bjgg(+ zV45i<1Q1S6*&RZ)mA=9Qk23Pi3_-zX>ST8wrOdiAIf^^Mh^}vf+&#cL7^R4BRy2@LQ zS?X%ez_5nVKte1w&tvMLA@2IO9}MErdM95;hhp=`n7-+ZiC<-*#THq!z(9?CG|*^x z8q1-0e&@o_*idoteCILg^n|GG%?KSUgJx{JeeAZ%KTcJ!x@IkhF%q2rA8}N1y%Epq zmo^B6=C#z*1bK|r4@dkL25_8|V;;4;rV>;AzilpSo6PW`XFC{|2-l2i@x>#&pVbMY z>EL)DKJy1@hm-l8-iX+C?T5P|Gn{$1O0`Dlw=|=%#?yp-#xfGljU^kBSb1oG>_kK2 z(|6{DY__`%$(NtS><@7o?Vz!_wWRcwmNb;9*Bmiw9G}B(QU$eGe-b)5(SF87R9_%7 zo#`wnmEW1KK~T7i`UL8{OtU1{3P_iR_6|+G9`(sT_}UN5uS1cx)e4X(nIt7}eh^Pb$Kn%OhzPAadd#rzJat?j`EpX##m zy4s5AGf=_hGiFuHI+dsy(<-LVt}#;`Q*L={Yf9~RR!PnD@>veWDOM@3vUMe;vu2l6W_;CID>4%`L+Wv_`)&hgoDtx^P~fn`0#X4EM@a)S(6)GKlh(8vu|wH<;3k4TK-O#a zt$@m!8=a-?jSUUZ&i?RfwPR7NmQ`Uib-yJq!k4e=P=(HKC_5KS=00=gPV69$e!1;y zo9DN=USWfft9L2uFNm6x>pM%$Thbo^nLRLN%^hAgyqC^RkAY52-BNHrwabN@$pV?S zi}nNNmei}JFJ>RR9=d0!`VjS)b>Wd z?zwrqZB@9vY?obblF{!i7_qvvHNeakZ&%yaN!obHa!)H$nyv6^mEFa%rd8kOZ5!G) zW9CAYw{^6)w3q?A?F{HVZ2{6WA-nkQO7xPf%dGccNkH*7dL-omUl2%w9+Ji(6Wx4?^*_%E>RLqO*cC0Uc~yh+A>_ zsX3hG6IS#E z2js-!e;0nUm=}3FeO*0lw_Z(b9x{+2o;xf&%((#0Ig$s2to22*Z4S&$EI}46V%~z! zhj~bDN?^CB(MsZ6QY}tIhc_=dTz%~;D++Wd zFpDeeYx>tFahhu{CBPk{KR;&S^8PZJtyW)@cKuN*@q1NO^XDNDU+j=JuTd6p*x9tJS2S2iajB9EMr$0Go!xW9J_SzYROm%f&wooD zYaJ-evZ3On(~)n6y5XpEhJMGH4qPbsJ#vNQkfG+lW1?k3wPc4GtIY6FB8?f@iXV?j zyL6j8+4USPo=ACf%m8V^Iyn)km^xaHJSGidEM4r85z=Lp;ZdkD4~_kg6rMi>k&H z)gCfYz6=^-!4x^&hk7h7Djg;O3#`UU>_Qg}E?qDT4W@{tOG}HAgNDv1TMn-x-JKN^ zn+t?ZkX}Yn(V)S_WedDn5Bg8D9zQJ?qe$~4xU~%em+4H5u5DV7TTezhWVFNfEyih^ z-VaetNkZMMwxp?vdgCQZOXXm?WPxQp4YEnJ~k2ILC&#E zoRzR(s;p}u=!eN%JvO<`VRp|E-$oemoVFP^CSjzo0VA6OFifRz@#1-Lsg0vvVM}wD z!U0TNpxSjiE#je!-C3l0cpZ=1G{o znS*tgYh%rczC`ui%%cy4M9vK7Mxq~_1r}hVjTB)~^4Ak_ zBLi(@kKQ^tV{1o_@uPcMGL-;h^C62!VteSw>5sSo!08F6;@G;Xk#lNTD%sA(fQMvy zXj@Y$qd!)MnhU%X;SB?#UF_LYOdR#9qacox>ST(HQe6qic+kN9_&?C-OpqI9QYCST z#Fkma>)Ia7gg&5Ak4)zmYH`jDGZvH58jEZT8gvQmypVZ4H?`DtUL)Q#Iwy#%JY-fk zCgpvv&hw&~?Yix^^|x=&+rGA@x>?R|Dn)UU&g(sfm43Tf{Xqm7X_D53*360MOhHuIF$GDLDw7~hDBtMM4mbT+j6)BdKM>yN6}gpz4<1-qUS2V8 z$h=|0=H(8q!1qIQD~238f7raC1BaNg6N}(dcyzcoDVxXQz>|<83DyJhjJUUnoz^Hx zJ(Frbma5^nCK(X0a0oB5J44!BI#dFYst>0t}xQ%6Ui&K5EQiyi^dgFJ$WYolUb<@}|zhAB? zoLOwrPGHUc2PO75jY(vm7eD_!Mz+qAb8yt9$6Cpe#$xhJ7dR*$1U$}p?SYpVK|S!Y zg9>~Ku#=8$uaTxpmtq_O)nP&%o_k@`!&!~*d@L>R@!@f|cpFqmc7?k2u19DwI{k&@ zqb*akM@!KS+YD$d$X}r~O%gP?xgcWs2 z8AhyMm(9lxC~|5g9Y%&3_z!@?O56mJ(*>M}qFYrr%jFw5b4Ofcgzx<^=IkGyOhlQ0 zIMlT-fmuX7PCw;tI*z#(h`vej7@ly-C>tJ#Y8Q?PJ%+;Gp!HE&Qi=T;X&E@vASPXd z)ZYlZB8ejV=7Q)6R{z9AagVO4(1UKNnYa_dzbUM`J1w5q=HO`=cf)ZqEtgtwA|zuf z+@D+M{)@g>$^n zrc9ky3$u~au!E!^xOQNjO>ICyI8BBN07^$8biZm}9HIXQj;@y1*6fcKgfA8ZDlMl1 zfD;*<$K*Ux;)s%|jnU~9uIJCUk?BNMm6S|irqCOqE|`*GpQO3J>1sO~x?mUSSRyt! zUW@<35^V4ASPI2zd*F*6Mje!ZQ=xO56ZNy#;Y8XRu}^gseA>`gu>DejHJ)6AkV%j< zVO4Qs4cr-EbTFq8U!Hm}?i3h4y$yDrDGJ+H-SblJdeMT^3mTdjvWBKg;$o+4cuS6Y zHLJSWbeUourV&-_h4mi53kVW$fUm&3t67>D^AGFSflEP+a9AnBos^sb5?hYkF=EQK z!G1M3+Od8riDS}ewmJGCiwYc5Ci|tFF~e9@4N~QP5R+8d`K>07LC$mLFX#x^gqids8OwC;WIX_TgrT@2~1l{K=V28FAYxnI@%W~&3zJ~#rgRo4na0d*_x zAkoRh{?_Glf7|ZX=N)QZSpmHgb(6fM?xKEH3xTtRhUM8VQ`uA}T>!d`vl5)mLbp^| z+!f>m%-#UovFflZ1a55KvttBOg_Bv+L8@?08%fgjNbJC-T$kLC=&t!ey9RJltPbvW znFc{YB5;>%T!4kAjO)q%@xn0@X>Y@%zH5Q=Ov%HYLotc6QHee;^YsdQrXxK-I(K5s z#68AzKBJI{lj8Z#MwE~)Av|YTrWfUpL zb00z^4U1;)G~s)7BZdo{u_@Xv&-JTb0I*7NqG4J&0<*%y7ngm6q?yXP%-uMMV5ATv z=IfVi$d;xV+FciyrQ+RQf?g0vYP{$wQDq*F=E7~45&Gh%G&-h9DX$7yvG_@0lSzL9TAk(1uW+Q(;;7 zN{n`l6~zUsAui1@F-3J{<&_gK&|*G|1nye7CjtgOHwK1dVq}Hc-)*npNEL=;np?f= z?qh$<4C?#I$ZX&Fg$R7xKtJ1S^<`e#DcaxB+-&aVm+~gIS7)b#HPF|^wMU{fZ0m7{i~6Ff7)nbS zjWT0jUDWOkXHDuVr)k1{lyt3B;}{`gLTDBoXL=1B++?L3ZE-C6v~}IhZ+jJ~K{u_q zH;8$jVs#e?`mVD@zKc!9VOa>feJL5tWfCrfN&2R&<{}%B+{>_Y3OnSDLc3hDg0dJ%Y(rCv^@y5GP=@7{@=NCDX2mK~ldQ3dfnLlZXR^(blmK@JJwRNqby zk#>j<6PP+{VgkG%uyx zzephZ7QmUf;gsb3Q+R?j8USz-TY)kPtLiF6HV9SKL;_HG2^siY7m4p;J={^@9aJc1 zgQd0e7L}KlrDF>l@#fX`DYbR*9}qX>abqVIOMdcp9l+@5k6=pm5tt_a>Xj8ZKTSn! z4;M)!g=5xNid{SFPK9ZW^ZT`oIU2S6k@CZ7>ZOrq)YOM zsM^NFAwXk&4IL`147Hd@qAiF5|FL*Bn6Tq5tMKr_4l~}pi>p3(r6tZ1>I>^@n@~TD zA2`DrV_$}wpVw0)YUvgF&KQI-24XC%k^Ab#1I6`6c#iOLZpzE zYK1|eILaz)frVvNDsE_ux{_6<pAq76U>^VQkxoYS=6!mN;5WTq37G%kuM# z{3uL=DJ^d3RbG_rbzEbw{s$y`fonxML<(QrP$;A^rU>sAL)`xI2ex0m29P!6n

U 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 Ldf@*j9{9fiE?E+& literal 0 HcmV?d00001 diff --git a/scripts/install-profile.sh b/palace-scripts/install-profile.sh similarity index 100% rename from scripts/install-profile.sh rename to palace-scripts/install-profile.sh diff --git a/scripts/ios-binaries-check.sh b/palace-scripts/ios-binaries-check.sh similarity index 100% rename from scripts/ios-binaries-check.sh rename to palace-scripts/ios-binaries-check.sh diff --git a/scripts/ios-binaries-upload.sh b/palace-scripts/ios-binaries-upload.sh similarity index 100% rename from scripts/ios-binaries-upload.sh rename to palace-scripts/ios-binaries-upload.sh diff --git a/scripts/ios-check-version.sh b/palace-scripts/ios-check-version.sh similarity index 100% rename from scripts/ios-check-version.sh rename to palace-scripts/ios-check-version.sh diff --git a/scripts/release-notes.sh b/palace-scripts/release-notes.sh similarity index 100% rename from scripts/release-notes.sh rename to palace-scripts/release-notes.sh diff --git a/scripts/setup-repo-drm.sh b/palace-scripts/setup-repo-drm.sh similarity index 100% rename from scripts/setup-repo-drm.sh rename to palace-scripts/setup-repo-drm.sh diff --git a/scripts/setup-repo-nodrm.sh b/palace-scripts/setup-repo-nodrm.sh similarity index 100% rename from scripts/setup-repo-nodrm.sh rename to palace-scripts/setup-repo-nodrm.sh diff --git a/scripts/testflight-upload.sh b/palace-scripts/testflight-upload.sh similarity index 100% rename from scripts/testflight-upload.sh rename to palace-scripts/testflight-upload.sh diff --git a/scripts/update-certificates.sh b/palace-scripts/update-certificates.sh similarity index 100% rename from scripts/update-certificates.sh rename to palace-scripts/update-certificates.sh diff --git a/scripts/xcode-archive.sh b/palace-scripts/xcode-archive.sh similarity index 100% rename from scripts/xcode-archive.sh rename to palace-scripts/xcode-archive.sh diff --git a/scripts/xcode-build-nodrm.sh b/palace-scripts/xcode-build-nodrm.sh similarity index 100% rename from scripts/xcode-build-nodrm.sh rename to palace-scripts/xcode-build-nodrm.sh diff --git a/scripts/xcode-export-adhoc.sh b/palace-scripts/xcode-export-adhoc.sh similarity index 100% rename from scripts/xcode-export-adhoc.sh rename to palace-scripts/xcode-export-adhoc.sh diff --git a/scripts/xcode-export-appstore.sh b/palace-scripts/xcode-export-appstore.sh similarity index 100% rename from scripts/xcode-export-appstore.sh rename to palace-scripts/xcode-export-appstore.sh diff --git a/scripts/xcode-settings.sh b/palace-scripts/xcode-settings.sh similarity index 100% rename from scripts/xcode-settings.sh rename to palace-scripts/xcode-settings.sh diff --git a/scripts/xcode-test.sh b/palace-scripts/xcode-test.sh similarity index 100% rename from scripts/xcode-test.sh rename to palace-scripts/xcode-test.sh diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 000000000..4571c876e --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# +# Bootstrap the repository. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo " --overwrite-secrets Overwrite secret files." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script boostraps the repository and makes it ready to build." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +overwriteSecrets=0 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + --overwrite-secrets) + overwriteSecrets=1 + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +basename "$0" + +info "Bootstrapping the repo..." + +#git submodule deinit adept-ios +#git rm -rf adept-ios +#git submodule deinit adobe-content-filter +#git rm -rf adobe-content-filter +#git submodule deinit ios-drm-audioengine +#git rm -rf ios-drm-audioengine +#git submodule deinit ios-audiobook-overdrive +#git rm -rf ios-audiobook-overdrive + +if [ "$BUILD_CONTEXT" != "ci" ]; then + git submodule update --init --recursive +fi + +# Copy in Carthage files, if not there already +if [ ! -f "Cartfile" ]; then + cp Cartfile.example Cartfile +fi +if [ ! -f "Cartfile.resolved" ]; then + cp Cartfile.resolved.example Cartfile.resolved +fi + +if [ ! -f "APIKeys.swift" ]; then + cp Palace/AppInfrastructure/APIKeys.swift.example Palace/AppInfrastructure/APIKeys.swift +fi + +if [ ! -f "PalaceConfig/ReaderClientCert.sig" ]; then + cp PalaceConfig/ReaderClientCert.sig.example PalaceConfig/ReaderClientCert.sig +fi + +# Reveal secrets +if [ $overwriteSecrets -eq 0 ]; then + ./scripts/reveal-secrets.sh || exit $? +else + ./scripts/reveal-secrets.sh --overwrite || exit $? +fi + +# Build 3rd party dependencies +./scripts/build-3rd-party-dependencies.sh + +# Reset the build number +./scripts/version.sh --reset-build-number || exit $? diff --git a/scripts/build-3rd-party-dependencies.sh b/scripts/build-3rd-party-dependencies.sh index 5cdcc2534..f624e1a82 100755 --- a/scripts/build-3rd-party-dependencies.sh +++ b/scripts/build-3rd-party-dependencies.sh @@ -1,45 +1,62 @@ #!/bin/bash -# SUMMARY -# This script integrates secrets, regenerates Readium headers, wipes -# the Carthage folder, and finally checks out and rebuilds all Carthage -# dependencies. # -# USAGE -# Run this script from the root of ios-core repo: +# Build 3rd party dependecies for E-kirjasto. # -# ./scripts/build-3rd-party-dependencies.sh [--no-private] +# Version 1.0.0 # -# PARAMETERS -# --no-private: skips integrating private secrets. -# -# NOTE -# This script is idempotent so it can be run safely over and over. -set -eo pipefail +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script builds 3rd party dependencies for E-kirjasto." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} -fatal() -{ - echo "$0 error: $1" 1>&2 - exit 1 +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 } -if [ "$BUILD_CONTEXT" == "" ]; then - echo "Building 3rd party dependencies..." -else - echo "Building 3rd party dependencies for [$BUILD_CONTEXT]..." -fi +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} -case $1 in - --no-private ) +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 ;; - *) - # update dependencies from Certificates repo - ./scripts/update-certificates.sh + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 ;; -esac + esac +done + + +basename "$0" + +info "Building 3rd party dependencies..." -(cd readium-sdk; sh MakeHeaders.sh Apple) || fatal "Error making Readium headers" +(cd readium-sdk; bash MakeHeaders.sh Apple) || fatal "Error making Readium headers" $? -# rebuild all Carthage dependencies from scratch -./scripts/build-carthage.sh $1 +# Rebuild Carthage dependencies +./scripts/build-carthage.sh || fatal "Carthage build failed" $? diff --git a/scripts/build-carthage.sh b/scripts/build-carthage.sh index 0417210c9..b26df47b8 100755 --- a/scripts/build-carthage.sh +++ b/scripts/build-carthage.sh @@ -1,51 +1,63 @@ #!/bin/bash -# SUMMARY -# Sets up and build dependencies for the Palace and Palace-noDRM targets # -# SYNOPSIS -# ./scripts/build-carthage.sh [--no-private ] +# Builds Carthage dependencies for E-kirjasto. # -# PARAMETERS -# --no-private: skips building private repos. +# Version 1.0.0 # -# USAGE -# Make sure to run this script from a clean checkout and from the root -# of ios-core, e.g.: -# -# git checkout Cartfile -# git checkout Cartfile.resolved -# ./scripts/build-carthage.sh -# -# NOTES -# If working on R2 integration, use the `build-carthage-R2-integration.sh` -# script instead. - -set -eo pipefail -if [ "$BUILD_CONTEXT" == "" ]; then - echo "Building Carthage..." -else - echo "Building Carthage for [$BUILD_CONTEXT]..." +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script builds Carthage dependencies for E-kirjasto." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +basename "$0" + +if ! command -v carthage > /dev/null 2>&1; then + fatal "Carthage not found, have you installed it (brew install carthage)?" 66 fi -# deep clean to avoid any caching issues -rm -rf ~/Library/Caches/org.carthage.CarthageKit -rm -rf Carthage - -# for DRM-enabled build only -if [ "$1" != "--no-private" ]; then - if [ "$BUILD_CONTEXT" == "ci" ]; then - CERTIFICATES_PATH_PREFIX="." - else - CERTIFICATES_PATH_PREFIX=".." - fi - - swift $CERTIFICATES_PATH_PREFIX/mobile-certificates/Certificates/Palace/iOS/AddLCP.swift - - ./ios-drm-audioengine/scripts/fetch-audioengine.sh -fi - -echo "Carthage build..." -carthage bootstrap --use-xcframeworks --platform ios - +info "Building Carthage..." +carthage bootstrap --use-xcframeworks --platform ios \ + || fatal "Carthage build failed" $? diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 000000000..21aa49c0c --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +# +# Build the E-kirjasto iOS app. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help] [BUILD_TYPE] [config:CONFIG]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo "BUILD_TYPE Build type to use. Available build types:" + echo " - debug (default): debug build" + echo " - release: release build (requires signing keys)" + echo " - release_upload: release build and upload to Testflight" + echo " - requires signing keys and App Store Connect API key" + echo "CONFIG Configuration flavor to use. Available configurations:" + echo " - ellibs: Uses backend: circulation-beta.ellibs.com" + echo " - dev (default): Uses backend: lib-dev.e-kirjasto.fi" + echo " - beta: Uses backend: lib-beta.e-kirjasto.fi" + echo " - production: Uses backend: lib.e-kirjasto.fi" + # Wrap after 80 characters --> ####################################################### + echo + echo "This script builds the E-kirjasto iOS app. This is mostly used for" + echo "CI builds, but can be used locally as well." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +buildType="debug" +config="config:production" +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + # Build type + debug|release|release_upload) + buildType="$1" + shift + ;; + # Build configuration + config:ellibs|config:dev|config:beta|config:production) + config="$1" + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +basename "$0" + +info "Executing '$buildType' build ($config)" + +if [[ "$buildType" == *"upload"* ]]; then + # Increment the last digit of the build number based on build configuration + targetLastDigit=0 + [[ "$config" == *"production"* ]] && targetLastDigit=1 + [[ "$config" == *"beta"* ]] && targetLastDigit=2 + [[ "$config" == *"dev"* ]] && targetLastDigit=3 + [[ "$config" == *"ellibs"* ]] && targetLastDigit=4 + ./scripts/version.sh --increment-build-number-last-digit $targetLastDigit || exit $? +fi + +./scripts/fastlane.sh ios "build_$buildType" "$config" || exit $? diff --git a/scripts/clean.sh b/scripts/clean.sh new file mode 100755 index 000000000..94353d921 --- /dev/null +++ b/scripts/clean.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# +# Clean the E-kirjasto iOS app build. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script (agressively) cleans the E-kirjasto iOS app build." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +basename "$0" + +info "Cleaning..." + +# xcodebuild's clean fails way too easily, which isn't great for a "clean" command +#xcodebuild -project Palace.xcodeproj clean || exit $? + +rm -fr Carthage 2> /dev/null +sudo rm -fr "$HOME/Library/Developer/Xcode/DerivedData/"* || exit $? + +echo +info "Remember to bootstrap again:" +echo " ./scripts/bootstrap.sh" +echo diff --git a/scripts/fastlane.sh b/scripts/fastlane.sh new file mode 100755 index 000000000..80cb2ad2e --- /dev/null +++ b/scripts/fastlane.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# +# Fastlane wrapper. +# +# Version 2.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the Fastlane project directory, or fail +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +# Set some environment variables to make Fastlane work smoothly +export LC_ALL="en_US.UTF-8" +export LANG="en_US.UTF-8" + +if command -v bundle > /dev/null 2>&1; then + bundle install || exit $? + bundle exec fastlane "$@" || exit $? +elif command -v fastlane > /dev/null 2>&1; then + fastlane "$@" || exit $? +else + fatal "Could not find Fastlane or the Ruby bundler, please install Fastlane" 65 +fi diff --git a/scripts/release-checks.sh b/scripts/release-checks.sh new file mode 100755 index 000000000..2ef276dcf --- /dev/null +++ b/scripts/release-checks.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# +# Run release checks for the E-kirjasto iOS app. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo " --minimal Only perform minimal checks, just for upload." + echo " --skip-transifex-download Skip downloading new Transifex strings." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script checks if a new E-kirjasto version is ready for release." + echo "Release checks include:" + echo "- the version number must be increased from the version in the main branch" + echo "- the version can't contain any suffix (App Store Connect doesn't allow them)" + echo "- Transifex cannot have any new strings that have not been committed to Git" + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +minimal=0 +skipTransifexDownload=0 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + --minimal) + minimal=1 + shift + ;; + --skip-transifex-download) + skipTransifexDownload=1 + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +# +# Get a string for comparing version. +# +# This takes a version string that follows the semantic versioning format +# (basically major.minor.patch, any suffix is ignored) and returns a comparison +# string. These comparison strings can be compared alphabetically to find which +# version is higher. +# +getVersionComparisonString() { + version="$1" + if grep -E '^[0-9]+\.[0-9]+\.[0-9]+' <<< "$version" > /dev/null 2>&1; then + # The version has correct syntax (at least major.minor.patch, suffix is not checked) + version="${version//[!0-9]/ }" + read -ra version <<< "$version" + major="${version[0]}" + minor="${version[1]}" + patch="${version[2]}" + echo "$(printf %04d "$major")$(printf %04d "$minor")$(printf %04d "$patch")" + else + # Incorrect format, treat the same as 0.0.0 + echo "000000000000" + fi +} + + +basename "$0" + +# Check for a suffix in the version +info "Checking for suffix in version name..." +currentVersion="$(./scripts/version.sh --get-version)" +currentVersionWithoutSuffix="$(grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' <<< "$currentVersion")" +if [[ "$currentVersion" != "$currentVersionWithoutSuffix" ]]; then + suffix="${currentVersion:${#currentVersionWithoutSuffix}}" + fatal "The version in the current commit ($currentVersion) must not have any suffix, but has '$suffix'" 68 +fi + +if [ $minimal -eq 1 ]; then + info "Minimal checks done, exiting..." + exit 0 +fi + +info "Checking for version increment (comparing with the main branch)..." +# Find Git diff of the version change between the current commit and main +git fetch --no-recurse-submodules origin main +versionDiff="$(git diff -U0 origin/main -- Palace.xcodeproj/project.pbxproj | grep -E '^[+-].*MARKETING_VERSION ?=')" +if [ -z "$versionDiff" ]; then + fatal "The version number must be increased compared to the main branch, but no changes were found" 66 +fi + +# Get the old version (main branch) and the new version (current commit) +oldVersion="$(grep '^-' <<< "$versionDiff")" +# Get only the first changed line (multiple lines contain the version) +oldVersion="$(echo "$oldVersion" | head -1)" +# Get only the version (strip everything else around it) +oldVersion="$(grep -Eo '[0-9]+\.[0-9]+\.[0-9]+[^"'\'';]*' <<< "$oldVersion")" +info "Old version: $oldVersion" +newVersion="$(grep '^+' <<< "$versionDiff")" +# Get only the first changed line (multiple lines contain the version) +newVersion="$(echo "$newVersion" | head -1)" +# Get only the version (strip everything else around it) +newVersion="$(grep -Eo '[0-9]+\.[0-9]+\.[0-9]+[^"'\'';]*' <<< "$newVersion")" +info "New version: $newVersion" + +oldVersionComparison="$(getVersionComparisonString "$oldVersion")" +newVersionComparison="$(getVersionComparisonString "$newVersion")" +if [[ $oldVersionComparison < $newVersionComparison ]]; then + info "The version in the current commit ($newVersion) is newer than the version in the main branch ($oldVersion), all good!" +else + fatal "The version in the current commit ($newVersion) must be higher than the version in the main branch ($oldVersion)" 67 +fi + + +if [ $skipTransifexDownload -eq 1 ]; then + info "Skipping Transifex download because of flag..." +else + info "Running Transifex download (skipping upload)..." + ./scripts/transifex.sh --skip-upload || exit $? +fi + +info "Checking that there are no new Transifex strings..." +changedTransifexFiles="$(git diff --name-only HEAD | grep txstrings.json)" +if [ -z "$changedTransifexFiles" ]; then + info "Found no changes to Transifex strings, all good!" +else + warn "Found changes to the following Transifex files:" + echo "$changedTransifexFiles" + message="Found unexpected changes to localizations on Transifex download, please commit any changes" + if [ -n "$GITHUB_ACTIONS" ]; then + # In GitHub Actions, show warnings, but don't fail the CI build + while IFS= read -r filepath; do + echo "::error file=$filepath::$message" + done <<< "$changedTransifexFiles" + else + # Locally, exit with an error code + fatal "$message" 69 + fi +fi diff --git a/scripts/reveal-secrets.sh b/scripts/reveal-secrets.sh new file mode 100755 index 000000000..3e2dc02d5 --- /dev/null +++ b/scripts/reveal-secrets.sh @@ -0,0 +1,128 @@ +#!/bin/bash + +# +# Reveal E-kirjasto iOS secrets. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help] [--overwrite]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo " --overwrite Ovewrite existing secret files." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script reveals E-kirjasto build secrets from environment variables." + echo + echo "List of secret environment variables:" + echo "- EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64" + echo " - Fastlane JSON file with the App Store Connect API key (base64 encoded)" + echo "- EKIRJASTO_LIBLCP_DEPENDENCY_SECRET" + echo " - the liblcp secret dependency (only the secret part, not the full path)" + echo "- EKIRJASTO_IOS_TRANSIFEX_TOKEN" + echo " - Transifex token (for localizations)" + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +overwrite=0 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + # Overwrite existing secret files + --overwrite) + overwrite=1 + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +base64_to_file() { + base64Input="$1" + outputFile="$2" + info "Revealing secret file: $outputFile" + echo "$base64Input" | base64 --decode > "$outputFile" +} + +reveal_file() { + filepath="$1" + envVariableName="$2" + envVariableValue="${!envVariableName}" + if [ "$overwrite" -ne 1 ] && [ -f "$filepath" ]; then + info "File already exists, not overwriting: $filepath" + else + if [ -z "$envVariableValue" ]; then + warn "Not revealing $filepath, because $envVariableName is not set" + else + base64_to_file "$envVariableValue" "$filepath" + fi + fi +} + + +basename "$0" + +reveal_file fastlane/app-store-connect-api-key.json EKIRJASTO_FASTLANE_APP_STORE_CONNECT_API_KEY_JSON_BASE64 + +# macOS has an ancient version of sed, so find the correct arguments to use +sedArgs=(-i) +# Use the ancient invocation, if even using `--version` gives an error +if ! sed --version &> /dev/null; then + sedArgs=(-i '') +fi + + +if [ -z "$EKIRJASTO_LIBLCP_DEPENDENCY_SECRET" ]; then + info "Not revealing liblcp dependency secret, EKIRJASTO_LIBLCP_DEPENDENCY_SECRET is not set" +else + info "Revealing revealing liblcp dependency secret" + sed "${sedArgs[@]}" 's#/test/liblcp.json" ~> 3.0.0#/'"$EKIRJASTO_LIBLCP_DEPENDENCY_SECRET"'/liblcp.json" ~> 3.1.1#' \ + ./Cartfile + sed "${sedArgs[@]}" 's#/test/liblcp.json" "3.0.0"#/'"$EKIRJASTO_LIBLCP_DEPENDENCY_SECRET"'/liblcp.json" "3.1.1"#' \ + ./Cartfile.resolved +fi + +if [ -z "$EKIRJASTO_IOS_TRANSIFEX_TOKEN" ]; then + info "Not revealing Transifex token, EKIRJASTO_IOS_TRANSIFEX_TOKEN is not set" +else + info "Revealing Transifex token" + # TODO:SAMI: Move the Transifex token to a config file, having it in the code feels *dirty* + sed "${sedArgs[@]}" 's#token: ""#token: "'"$EKIRJASTO_IOS_TRANSIFEX_TOKEN"'"#' \ + ./Palace/Utilities/Localization/Transifex/TransifexManager.swift + + warn "To avoid accidentally committing the Transifex token, Git will ignore changes to TransifexManager.swift" + git update-index --assume-unchanged ./Palace/Utilities/Localization/Transifex/TransifexManager.swift + warn "To continue tracking changes to the file, run the following command:" + echo " git update-index --no-assume-unchanged ./Palace/Utilities/Localization/Transifex/TransifexManager.swift" + echo +fi diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh new file mode 100755 index 000000000..204e090d2 --- /dev/null +++ b/scripts/run-tests.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# +# Run E-kirjasto iOS tests. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script runs E-kirjasto unit tests." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + + +basename "$0" + +info "Running tests" + +./scripts/fastlane.sh ios test diff --git a/scripts/setup-repo-nodrm-github.sh b/scripts/setup-repo-nodrm-github.sh deleted file mode 100755 index 5d0a09072..000000000 --- a/scripts/setup-repo-nodrm-github.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# SUMMARY -# Sets up the ios-core repo for running Palace without DRM support. -# -# USAGE -# You only have to run this script once after checking out the related repos. -# Run it from the root of ios-core, e.g.: -# -# ./scripts/setup-repo-nodrm.sh -# -# NOTES -# 1. On a fresh checkout this script will produce some errors while trying -# to deinit the adobe repos. This is expected and does not affect the -# build process. - -set -eo pipefail - -echo "Setting up repo for non-DRM build" - -#git submodule deinit adept-ios -#git rm -rf adept-ios -#git submodule deinit adobe-content-filter -#git rm -rf adobe-content-filter -#git submodule deinit ios-drm-audioengine -#git rm -rf ios-drm-audioengine -#git submodule deinit ios-audiobook-overdrive -#git rm -rf ios-audiobook-overdrive - -git submodule update --init --recursive - -# Remove private repos from Cartfile and Cartfile.resolved. -#sed -i '' "s#.*lcp.*##" Cartfile -#sed -i '' "s#.*lcp.*##" Cartfile.resolved - -if [ ! -f "APIKeys.swift" ]; then - cp Palace/AppInfrastructure/APIKeys.swift.example Palace/AppInfrastructure/APIKeys.swift -fi - -# These will need to be filled in with real values -if [ ! -f "PalaceConfig/GoogleService-Info.plist" ]; then - cp PalaceConfig/GoogleService-Info.plist.example PalaceConfig/GoogleService-Info.plist -fi -if [ ! -f "PalaceConfig/ReaderClientCert.sig" ]; then - cp PalaceConfig/ReaderClientCert.sig.example PalaceConfig/ReaderClientCert.sig -fi diff --git a/scripts/show-ci-info.sh b/scripts/show-ci-info.sh new file mode 100755 index 000000000..c4578be74 --- /dev/null +++ b/scripts/show-ci-info.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# +# Show CI info. +# +# 1.3.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +basename "$0" + +echo "----------------------------------------" +echo "COMMIT_SHA=$COMMIT_SHA" +echo "BRANCH_NAME=$BRANCH_NAME" +echo "TARGET_BRANCH_NAME=$TARGET_BRANCH_NAME" +echo "----------------------------------------" +echo +echo "Checking if secrets are available, fake secret: $TEST_SECRET" +if [ -z "$TEST_SECRET" ]; then + echo "::warning title=Secrets are unavailable::Secrets are not available, this could be a non-member PR (there could be build issues)" +else + echo "Secrets are available!" +fi diff --git a/scripts/transifex.sh b/scripts/transifex.sh new file mode 100755 index 000000000..61b68d44c --- /dev/null +++ b/scripts/transifex.sh @@ -0,0 +1,201 @@ +#!/bin/bash + +# +# Transifex iOS wrapper. +# +# Version 1.0.0 +# + +basename "$0" + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo " --append-tags Append the listed tags to all strings (comma-separated)." + echo " --dry-run Perform a dry-run of an upload." + echo " --purge Purge any deleted source strings." + echo " --skip-upload Skip upload even if the Transifex secret is given." + # Wrap after 80 characters --> ####################################################### + echo + echo "This script uploads and downloads Transifex strings." + echo + echo "The Transifex token (required) and secret (optional) should be set by using the" + echo "EKIRJASTO_IOS_TRANSIFEX_TOKEN and EKIRJASTO_IOS_TRANSIFEX_SECRET environment" + echo "variables." + echo + echo "The script always downloads/pulls strings from Transifex, so the token" + echo "is required. The Transifex secret is optional, and if not given, then" + echo "upload/push will be skipped." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +appendTags="" +dryRun=0 +purge=0 +skipUpload=0 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + --append-tags=*) + appendTags="${1#*=}" + shift + ;; + --dry-run) + dryRun=1 + shift + ;; + --purge) + purge=1 + shift + ;; + --skip-upload) + skipUpload=1 + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 65 + ;; + esac +done + +if [[ "$appendTags" == *" "* ]]; then + fatal "No spaces allowed in --appendTags" +fi + +if [ $skipUpload -eq 1 ] && [ -n "$appendTags" ]; then + fatal "Cannot use --skip-upload and --append-tags together (cannot upload tags without uploading strings)" 66 +fi + +if [ $skipUpload -eq 1 ] && [ $dryRun -eq 1 ]; then + fatal "Cannot use --skip-upload and --dry-run together (dry-runs are only for uploads, not downloads)" 67 +fi + +if [ $skipUpload -eq 1 ] && [ $purge -eq 1 ]; then + fatal "Cannot use --skip-upload and --purge together (purge is only effective when uploading)" 68 +fi + +# Path to app's Transifex assets directory +assetsPath="Palace/Utilities/Localization/Transifex" + +if [ -z "${EKIRJASTO_IOS_TRANSIFEX_TOKEN}" ]; then + fatal "EKIRJASTO_IOS_TRANSIFEX_TOKEN is not defined" 69 +fi + +#------------------------------------------------------------------------ +# Download and verify Transifex. +# + +info "Downloading txios-cli (transifex-swift-cli)" + +mkdir -p temp +(cd temp && rm -rf txios-cli*) +curl -sLo temp/txios-cli.tar.gz https://github.com/transifex/transifex-swift-cli/archive/refs/tags/2.1.6.tar.gz \ + || fatal "Could not download Transifex" 70 + +# Extract +(cd temp && tar xf txios-cli.tar.gz && mv transifex-swift-cli* txios-cli) + +# Build +(cd temp/txios-cli && swift build -c release && cp .build/release/txios-cli ../../) +echo + +# NOTE: This would be nice, but the SHA256 sum changes on every build... +# When updating, generate this file with: sha256sum txios-cli > txios-cli.sha256 +#sha256sum -c txios-cli.sha256 \ +# || fatal "Could not verify txios-cli" 71 + +#------------------------------------------------------------------------ +# Apply Transifex to the project's string resources. +# + +if [ $skipUpload -eq 1 ]; then + info "Skipping Transifex upload because of flag..." +elif [ -z "${EKIRJASTO_IOS_TRANSIFEX_SECRET}" ]; then + echo + warn "EKIRJASTO_IOS_TRANSIFEX_SECRET is not defined, UPLOAD WILL BE SKIPPED" + echo +else + TRANSIFEX_PUSH_ARGS="--verbose" + + if [ $dryRun -eq 1 ]; then + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --dry-run" + fi + + if [ $purge -eq 1 ]; then + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --purge" + fi + + if [ -n "$appendTags" ]; then + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --append-tags=$appendTags" + fi + + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --project=Palace.xcodeproj" + + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --token=${EKIRJASTO_IOS_TRANSIFEX_TOKEN}" + TRANSIFEX_PUSH_ARGS="${TRANSIFEX_PUSH_ARGS} --secret=${EKIRJASTO_IOS_TRANSIFEX_SECRET}" + + info "Uploading Transifex strings" + + ./txios-cli push ${TRANSIFEX_PUSH_ARGS} \ + || fatal "Could not upload Transifex strings" 73 + + info "Upload done!" + echo +fi + +TRANSIFEX_PULL_ARGS="--token=${EKIRJASTO_IOS_TRANSIFEX_TOKEN}" + +TRANSIFEX_PULL_ARGS="${TRANSIFEX_PULL_ARGS} --output=$assetsPath" + +# Find the list of langauges from the code +languages="$(grep 'let appLanguages' Palace/Utilities/Localization/Transifex/TransifexManager.swift | grep -Eo '".*"' | grep -Eo '[^"]+')" +IFS="," read -r -a languages <<< "$languages" +info "Languages: ${languages[*]}" +for language in "${languages[@]}"; do + TRANSIFEX_PULL_ARGS="${TRANSIFEX_PULL_ARGS} --translated-locales=$language" +done + +info "Downloading Transifex strings" + +./txios-cli pull ${TRANSIFEX_PULL_ARGS} \ + || fatal "Could not download Transifex strings" 74 + +info "Download done!" +echo + +#------------------------------------------------------------------------ +# Prettify Transifex JSON file. +# + +transifexFile="$assetsPath/txstrings.json" +info "Prettifying JSON file: $transifexFile" +# jq might be nicer than json_pp, but it's usually available on macOS and Linux +{ json_pp > "$transifexFile~"; } < "$transifexFile" +mv "$transifexFile~" "$transifexFile" diff --git a/scripts/version.sh b/scripts/version.sh new file mode 100755 index 000000000..1ad5d72eb --- /dev/null +++ b/scripts/version.sh @@ -0,0 +1,266 @@ +#!/bin/bash + +# +# Manage the version of the E-kirjasto iOS app. +# +# Version 1.0.0 +# + +trap 'trap - INT; exit $((128 + $(kill -l INT)))' INT + +# cd into the project root directory (or fail) +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." || exit 64 + +# Show command usage +show_usage() { + echo "Usage: $(basename "$0") [-h|--help] [OPTIONS]" + echo + # Wrap after 80 characters --> ####################################################### + echo "Options:" + echo "-h --help Show this help page." + echo " --check Check for inconsistencies in version and build" + echo " numbers (does *NOT* check the formatting)." + echo " --get-version Get the current version." + echo " --set-version=VERSION Set the version to VERSION." + echo " --get-build-number Get the current build number." + echo " --set-build-number=BUILD Set the build number to BUILD." + echo " --increment-build-number [AMOUNT]" + echo " Automatically* increment the build number." + echo " AMOUNT is optional and defaults to 1." + echo " --increment-build-number-last-digit DIGIT" + echo " Automatically* increment the build number's" + echo " last digit to DIGIT." + echo " --increment-build-number-next-10" + echo " Automatically* increment the build number," + echo " rounded to the nearest 10." + # Wrap after 80 characters --> ####################################################### + echo + echo " *) Automatic build number incrementation is based on the maxium build number" + echo " found locally or in App Store Connect (requires API key for Fastlane)." + echo + echo "This script manages the version of the E-kirjasto iOS app." + echo + echo "Note that the script doesn't really check the format of the version" + echo "at all, but it should follow the Semantic Versioning format." + echo +} + +fatal() { + echo "$(basename "$0"): FATAL: $1" 1>&2 + exit "${2:-1}" +} + +warn() { + echo "$(basename "$0"): WARNING: $1" 1>&2 +} + +info() { + echo "$(basename "$0"): INFO: $1" 1>&2 +} + +command="--get-version" +versionToSet="" +buildNumberToSet="" +buildNumberIncrementAmount=1 +buildNumberTargetLastDigit=0 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + --check) + command="$1" + shift + ;; + --get-version) + command="$1" + shift + ;; + --set-version) + command="$1" + shift + versionToSet="$1" + if [ -z "$versionToSet" ]; then + fatal "--set-version requires a version to set" 65 + fi + shift + ;; + --get-build-number) + command="$1" + shift + ;; + --set-build-number) + command="$1" + shift + buildNumberToSet="$1" + if [ -z "$buildNumberToSet" ]; then + fatal "--set-build requires a build number to set" 66 + fi + shift + ;; + --reset-build-number) + command="$1" + shift + buildNumberToSet=10000 + ;; + --increment-build-number) + command="$1" + shift + if [[ $1 =~ ^[0-9]+$ ]] ; then + buildNumberIncrementAmount=$1 + shift + fi + ;; + --increment-build-number-last-digit) + command="$1" + shift + if ! [[ $1 =~ ^[0-9]+$ ]] ; then + fatal "--increment-build-number-last-digit requires DIGIT argument" 67 + fi + buildNumberTargetLastDigit=$1 + shift + ;; + --increment-build-number-next-10) + command="$1" + shift + ;; + # Error on unrecognized parameters + *) + show_usage + fatal "Unrecognized parameter: $1" 68 + ;; + esac +done + + +projectFile="Palace.xcodeproj/project.pbxproj" + +get_build_number() { + buildNumberLines="$(grep -oE "CURRENT_PROJECT_VERSION = [\"']?[0-9]+\.?[0-9]*[^;\"']*" "$projectFile" | grep -oE "[0-9]+\.?[0-9]*")" + buildNumber="$(echo "$buildNumberLines" | head -1)" + while IFS= read -r line; do + [[ "$line" == "$buildNumber" ]] || return 1 + done <<< "$buildNumberLines" + echo "$buildNumber" +} + + +get_testflight_build_number() { + fastlaneOutput="$(./scripts/fastlane.sh print_testflight_build_number)" \ + || return 1 + testflightBuildNumber="$(echo "$fastlaneOutput" | grep "TESTFLIGHT_BUILD_NUMBER_MAX=" | grep -Eo '[0-9]+')" + echo "$testflightBuildNumber" +} + +set_build_number() { + buildNumberToSet="$1" + sed -i '' 's/CURRENT_PROJECT_VERSION = .*;/CURRENT_PROJECT_VERSION = "'"$buildNumberToSet"'";/g' "$projectFile" +} + +get_version() { + versionLines="$(grep -oE "MARKETING_VERSION = [\"']?[0-9]+\.[0-9]+\.[0-9]+[^;\"']*" "$projectFile" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+.*")" + version="$(echo "$versionLines" | head -1)" + while IFS= read -r line; do + [[ "$line" == "$version" ]] \ + || return 1 + done <<< "$versionLines" + echo "$version" +} + +set_version() { + versionToSet="$1" + sed -i '' 's/MARKETING_VERSION = .*;/MARKETING_VERSION = "'"$versionToSet"'";/g' "$projectFile" +} + + +case $command in + --check) + version="$(get_version)" \ + || fatal "All version numbers in '$projectFile' should match, but some of them are different" 69 + info "Version number: $version" + build_number="$(get_build_number)" \ + || fatal "All build numbers in '$projectFile' should match, but some of them are different" 70 + info "Build number: $build_number" + ;; + --get-version) + version="$(get_version)" \ + || fatal "All version numbers in '$projectFile' should match, but some of them are different" 71 + echo "$version" + ;; + --set-version) + info "NOTE: This script will not verify the format of the version string." + info "Project file: $projectFile" + info "Version before: $(get_version)" + info "Setting version to: $versionToSet" + set_version "$versionToSet" + info "Version was set to: $(get_version)" + ;; + --get-build-number) + build_number="$(get_build_number)" \ + || fatal "All build numbers in '$projectFile' should match, but some of them are different" 72 + echo "$build_number" + ;; + --set-build-number) + info "Setting build number..." + info "NOTE: This script will not verify the format of the build number string." + info "Project file: $projectFile" + info "Build number before: $(get_build_number)" + info "Setting build number to: $buildNumberToSet" + set_build_number "$buildNumberToSet" + info "Build number was set to: $(get_build_number)" + ;; + --reset-build-number) + info "Resetting build number..." + info "Project file: $projectFile" + info "Build number before: $(get_build_number)" + info "Setting build number to: $buildNumberToSet" + set_build_number "$buildNumberToSet" + info "Build number was set to: $(get_build_number)" + ;; + --increment-build-number) + info "Incrementing build number by 1, based on the maximum locally and in App Store Connect / Testflight..." + testflightBuildNumber="$(get_testflight_build_number)" \ + || fatal "Failed to get build number from Testflight via Fastlane (missing App Store Connect API key?)" 73 + currentBuildNumber="$(get_build_number)" + buildNumberMax=$((currentBuildNumber > testflightBuildNumber ? currentBuildNumber : testflightBuildNumber)) + buildNumberToSet=$((buildNumberMax + buildNumberIncrementAmount)) + info "Build number before: $currentBuildNumber" + info "Build number in Testflight: $testflightBuildNumber" + info "Incrementing build number by: $buildNumberIncrementAmount" + info "Setting build number to: $buildNumberToSet" + set_build_number "$buildNumberToSet" + info "Build number was set to: $(get_build_number)" + ;; + --increment-build-number-last-digit) + info "Incrementing the build number's last digit (to $buildNumberTargetLastDigit), based on the maximum locally and in App Store Connect / Testflight..." + testflightBuildNumber="$(get_testflight_build_number)" \ + || fatal "Failed to get build number from Testflight via Fastlane (missing App Store Connect API key?)" 74 + currentBuildNumber="$(get_build_number)" + buildNumberMax=$((currentBuildNumber > testflightBuildNumber ? currentBuildNumber : testflightBuildNumber)) + buildNumberMaxLastDigit=$((buildNumberMax % 10)) + buildNumberIncrementAmount=$(( (buildNumberTargetLastDigit + 10 - buildNumberMaxLastDigit) % 10 )) + # If the last digit is already correct, increment by 10 + [[ $buildNumberIncrementAmount == 0 ]] && buildNumberIncrementAmount=10 + buildNumberToSet=$((buildNumberMax + buildNumberIncrementAmount)) + info "Build number before: $currentBuildNumber" + info "Build number in Testflight: $testflightBuildNumber" + info "Incrementing build number by: $buildNumberIncrementAmount" + info "Setting build number to: $buildNumberToSet" + set_build_number "$buildNumberToSet" + info "Build number was set to: $(get_build_number)" + ;; + --increment-build-number-next-10) + info "Incrementing build number to the next 10, based on the maximum locally and in App Store Connect / Testflight..." + testflightBuildNumber="$(get_testflight_build_number)" \ + || fatal "Failed to get build number from Testflight via Fastlane (missing App Store Connect API key?)" 75 + currentBuildNumber="$(get_build_number)" + buildNumberMax=$((currentBuildNumber > testflightBuildNumber ? currentBuildNumber : testflightBuildNumber)) + buildNumberToSet=$(( (buildNumberMax / 10 + 1) * 10 )) + info "Build number before: $currentBuildNumber" + info "Build number in Testflight: $testflightBuildNumber" + info "Setting build number to (nearest 10): $buildNumberToSet" + set_build_number "$buildNumberToSet" + info "Build number was set to: $(get_build_number)" + ;; +esac