diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..3e63aca8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +version: 2 +updates: + - package-ecosystem: cargo + directory: "/" + schedule: + interval: weekly + day: tuesday + time: "02:00" + open-pull-requests-limit: 10 diff --git a/.github/workflows/appstore-build-publish.yml b/.github/workflows/appstore-build-publish.yml new file mode 100644 index 00000000..87c5b51f --- /dev/null +++ b/.github/workflows/appstore-build-publish.yml @@ -0,0 +1,181 @@ +# This workflow is adjusted compared to the one from the template to setup rust+cross + +name: Build and publish app release + +on: + release: + types: [published] + +env: + PHP_VERSION: 8.1 + +jobs: + build_and_publish: + runs-on: ubuntu-latest + + # Only allowed to be run on nextcloud-releases repositories + if: ${{ github.repository_owner == 'nextcloud-releases' }} + + steps: + ### Adjustments start ### + - name: musl-tools + run: | + sudo apt-get install musl-tools + - name: Checkout code + uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + target: x86_64-unknown-linux-musl + - name: cross + run: | + cargo install cross --locked + ### Adjustments end ### + + - name: Check actor permission + uses: skjnldsv/check-actor-permission@e591dbfe838300c007028e1219ca82cc26e8d7c5 # v2.1 + with: + require: write + + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: ${{ env.APP_NAME }} + + - name: Get appinfo data + id: appinfo + uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master + with: + filename: ${{ env.APP_NAME }}/appinfo/info.xml + expression: "//info//dependencies//nextcloud/@min-version" + + - name: Read package.json node and npm engines version + uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1 + id: versions + # Continue if no package.json + continue-on-error: true + with: + path: ${{ env.APP_NAME }} + fallbackNode: "^16" + fallbackNpm: "^7" + + - name: Set up node ${{ steps.versions.outputs.nodeVersion }} + # Skip if no package.json + if: ${{ steps.versions.outputs.nodeVersion }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 + with: + node-version: ${{ steps.versions.outputs.nodeVersion }} + + - name: Set up npm ${{ steps.versions.outputs.npmVersion }} + # Skip if no package.json + if: ${{ steps.versions.outputs.npmVersion }} + run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" + + - name: Set up php ${{ env.PHP_VERSION }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ env.PHP_VERSION }} + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer.json + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: "${{ env.APP_NAME }}/composer.json" + + - name: Install composer dependencies + if: steps.check_composer.outputs.files_exists == 'true' + run: | + cd ${{ env.APP_NAME }} + composer install --no-dev + + - name: Build ${{ env.APP_NAME }} + # Skip if no package.json + if: ${{ steps.versions.outputs.nodeVersion }} + run: | + cd ${{ env.APP_NAME }} + npm ci + npm run build + + - name: Check Krankerl config + id: krankerl + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: ${{ env.APP_NAME }}/krankerl.toml + + - name: Install Krankerl + if: steps.krankerl.outputs.files_exists == 'true' + run: | + wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb + sudo dpkg -i krankerl_0.14.0_amd64.deb + + - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl + if: steps.krankerl.outputs.files_exists == 'true' + run: | + cd ${{ env.APP_NAME }} + krankerl package + + - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile + if: steps.krankerl.outputs.files_exists != 'true' + run: | + cd ${{ env.APP_NAME }} + make appstore + + - name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }} + continue-on-error: true + id: server-checkout + run: | + NCVERSION=${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }} + wget --quiet https://download.nextcloud.com/server/releases/latest-$NCVERSION.zip + unzip latest-$NCVERSION.zip + + - name: Checkout server master fallback + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + if: ${{ steps.server-checkout.outcome != 'success' }} + with: + submodules: true + repository: nextcloud/server + path: nextcloud + + - name: Sign app + run: | + # Extracting release + cd ${{ env.APP_NAME }}/build/artifacts + tar -xvf ${{ env.APP_NAME }}.tar.gz + cd ../../../ + # Setting up keys + echo "${{ secrets.APP_PRIVATE_KEY }}" > ${{ env.APP_NAME }}.key + wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt" + # Signing + php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }} + # Rebuilding archive + cd ${{ env.APP_NAME }}/build/artifacts + tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }} + + - name: Attach tarball to github release + uses: svenstaro/upload-release-action@2b9d2847a97b04d02ad5c3df2d3a27baa97ce689 # v2 + id: attach_to_release + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz + tag: ${{ github.ref }} + overwrite: true + + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.APPSTORE_TOKEN }} + download_url: ${{ steps.attach_to_release.outputs.browser_download_url }} + app_private_key: ${{ secrets.APP_PRIVATE_KEY }} diff --git a/.github/workflows/lint-info-xml.yml b/.github/workflows/lint-info-xml.yml new file mode 100644 index 00000000..7b9e1c99 --- /dev/null +++ b/.github/workflows/lint-info-xml.yml @@ -0,0 +1,39 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint info.xml + +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: lint-info-xml-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + xml-linters: + runs-on: ubuntu-latest + + name: info.xml lint + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Download schema + run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd + + - name: Lint info.xml + uses: ChristophWurst/xmllint-action@39155a91429af431d65fafc21fa52ba5c4f5cb71 # v1.1 + with: + xml-file: ./appinfo/info.xml + xml-schema-file: ./info.xsd diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml new file mode 100644 index 00000000..f8d33751 --- /dev/null +++ b/.github/workflows/lint-php-cs.yml @@ -0,0 +1,40 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint php-cs + +on: pull_request + +permissions: + contents: read + +concurrency: + group: lint-php-cs-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + + name: php-cs + + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Set up php + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: 8.1 + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: composer i + + - name: Lint + run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) diff --git a/.github/workflows/lint-php.yml b/.github/workflows/lint-php.yml new file mode 100644 index 00000000..8d7f63f8 --- /dev/null +++ b/.github/workflows/lint-php.yml @@ -0,0 +1,60 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint php + +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: lint-php-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + php-lint: + runs-on: ubuntu-latest + strategy: + matrix: + php-versions: [ "8.0", "8.1", "8.2" ] + + name: php-lint + + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Lint + run: composer run lint + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: php-lint + + if: always() + + name: php-lint-summary + + steps: + - name: Summary status + run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index f23318a1..00000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Php Lint -on: [push, pull_request] - -jobs: - php-linters: - runs-on: ubuntu-20.04 - strategy: - matrix: - php-versions: ['7.3', '7.4', '8.0'] - name: php${{ matrix.php-versions }} lint - steps: - - name: Checkout - uses: actions/checkout@master - - name: Set up php${{ matrix.php-versions }} - uses: shivammathur/setup-php@master - with: - php-version: ${{ matrix.php-versions }} - coverage: none - - name: Install dependencies - run: composer i - - name: Lint - run: composer run lint - - php-cs-fixer: - name: php-cs check - runs-on: ubuntu-20.04 - steps: - - name: Checkout - uses: actions/checkout@master - - name: Set up php${{ matrix.php-versions }} - uses: shivammathur/setup-php@master - with: - php-version: 7.4 - tools: composer:v1 - coverage: none - - name: Install dependencies - run: composer i - - name: Run coding standards check - run: composer run cs:check diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 92e0f51e..57a4f326 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -1,7 +1,16 @@ -on: [push, pull_request] - name: Package +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + env: APP_NAME: notify_push @@ -14,7 +23,7 @@ jobs: run: | sudo apt-get install musl-tools - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -23,7 +32,7 @@ jobs: target: x86_64-unknown-linux-musl - name: cross run: | - cargo install cross + cargo install cross --locked - name: Setup krankler run: | wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.0/krankerl @@ -31,7 +40,7 @@ jobs: - name: Package app run: | ./krankerl package - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: ${{ env.APP_NAME }}.tar.gz path: build/artifacts/${{ env.APP_NAME }}.tar.gz diff --git a/.github/workflows/phpunit-mysql.yml b/.github/workflows/phpunit-mysql.yml new file mode 100644 index 00000000..c22492ae --- /dev/null +++ b/.github/workflows/phpunit-mysql.yml @@ -0,0 +1,163 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit mysql + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-mysql-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-mysql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0', '8.1', '8.2'] + server-versions: ['master'] + + services: + mysql: + image: ghcr.io/nextcloud/continuous-integration-mariadb-10.6:latest + ports: + - 4444:3306/tcp + env: + MYSQL_ROOT_PASSWORD: rootpassword + options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Enable ONLY_FULL_GROUP_BY MySQL option + run: | + sleep 20 + echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword + echo "SELECT @@sql_mode;" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword + + - name: Checkout server + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, mysql, pdo_mysql + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up dependencies + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin + ./occ app:enable --force ${{ env.APP_NAME }} + + - name: Check PHPUnit script is defined + id: check_phpunit + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:unit " | wc -l | grep 1 + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration script is defined + id: check_integration + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:integration " | wc -l | grep 1 + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:integration + + - name: Print logs + if: always() + run: | + cat data/nextcloud.log + + - name: Skipped + # Fail the action when neither unit nor integration tests ran + if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' + run: | + echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' + exit 1 + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-mysql + + if: always() + + name: phpunit-mysql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-mysql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-oci.yml b/.github/workflows/phpunit-oci.yml new file mode 100644 index 00000000..9b6d693b --- /dev/null +++ b/.github/workflows/phpunit-oci.yml @@ -0,0 +1,169 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit OCI + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-oci-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-oci: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + services: + oracle: + image: ghcr.io/gvenzl/oracle-xe:11 + + # Provide passwords and other environment variables to container + env: + ORACLE_RANDOM_PASSWORD: true + APP_USER: autotest + APP_USER_PASSWORD: owncloud + + # Forward Oracle port + ports: + - 1521:1521/tcp + + # Provide healthcheck script options for startup + options: >- + --health-cmd healthcheck.sh + --health-interval 10s + --health-timeout 5s + --health-retries 10 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, oci8 + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up dependencies + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 1521 + run: | + mkdir data + ./occ maintenance:install --verbose --database=oci --database-name=XE --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=autotest --database-pass=owncloud --admin-user admin --admin-pass admin + ./occ app:enable --force ${{ env.APP_NAME }} + + - name: Check PHPUnit script is defined + id: check_phpunit + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:unit " | wc -l | grep 1 + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration script is defined + id: check_integration + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:integration " | wc -l | grep 1 + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:integration + + - name: Print logs + if: always() + run: | + cat data/nextcloud.log + + - name: Skipped + # Fail the action when neither unit nor integration tests ran + if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' + run: | + echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' + exit 1 + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-oci + + if: always() + + name: phpunit-oci-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-oci.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-pgsql.yml b/.github/workflows/phpunit-pgsql.yml new file mode 100644 index 00000000..5e66fd2c --- /dev/null +++ b/.github/workflows/phpunit-pgsql.yml @@ -0,0 +1,159 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit pgsql + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-pgsql-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-pgsql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + services: + postgres: + image: ghcr.io/nextcloud/continuous-integration-postgres-14:latest + ports: + - 4444:5432/tcp + env: + POSTGRES_USER: root + POSTGRES_PASSWORD: rootpassword + POSTGRES_DB: nextcloud + options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, pgsql, pdo_pgsql + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up dependencies + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin + ./occ app:enable --force ${{ env.APP_NAME }} + + - name: Check PHPUnit script is defined + id: check_phpunit + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:unit " | wc -l | grep 1 + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration script is defined + id: check_integration + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:integration " | wc -l | grep 1 + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:integration + + - name: Print logs + if: always() + run: | + cat data/nextcloud.log + + - name: Skipped + # Fail the action when neither unit nor integration tests ran + if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' + run: | + echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' + exit 1 + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-pgsql + + if: always() + + name: phpunit-pgsql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-sqlite.yml b/.github/workflows/phpunit-sqlite.yml new file mode 100644 index 00000000..d613117f --- /dev/null +++ b/.github/workflows/phpunit-sqlite.yml @@ -0,0 +1,148 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit sqlite + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-sqlite-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-sqlite: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up dependencies + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin + ./occ app:enable --force ${{ env.APP_NAME }} + + - name: Check PHPUnit script is defined + id: check_phpunit + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:unit " | wc -l | grep 1 + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration script is defined + id: check_integration + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:integration " | wc -l | grep 1 + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:integration + + - name: Print logs + if: always() + run: | + cat data/nextcloud.log + + - name: Skipped + # Fail the action when neither unit nor integration tests ran + if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' + run: | + echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' + exit 1 + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-sqlite + + if: always() + + name: phpunit-sqlite-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-sqlite.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-summary-when-unrelated.yml b/.github/workflows/phpunit-summary-when-unrelated.yml new file mode 100644 index 00000000..484fdbb5 --- /dev/null +++ b/.github/workflows/phpunit-summary-when-unrelated.yml @@ -0,0 +1,68 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit summary + +on: + pull_request: + paths-ignore: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + +permissions: + contents: read + +jobs: + summary-mysql: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-mysql-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-oci: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-oci-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-pgsql: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-pgsql-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-sqlite: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-sqlite-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' diff --git a/.github/workflows/psalm-matrix.yml b/.github/workflows/psalm-matrix.yml new file mode 100644 index 00000000..70c75a88 --- /dev/null +++ b/.github/workflows/psalm-matrix.yml @@ -0,0 +1,63 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Static analysis + +on: + pull_request: + push: + branches: + - master + - main + - stable* + +concurrency: + group: psalm-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + static-analysis: + runs-on: ubuntu-latest + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: + ocp-version: [ 'dev-master', 'dev-stable27', 'dev-stable26', 'dev-stable25'] + + name: Nextcloud ${{ matrix.ocp-version }} + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Set up php + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: 8.0 + coverage: none + ini-file: development + extensions: redis + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: composer i + + - name: Install dependencies + run: rm composer.lock && composer require --dev nextcloud/ocp:${{ matrix.ocp-version }} --ignore-platform-reqs --with-dependencies + + - name: Run coding standards check + run: composer run psalm + + summary: + runs-on: ubuntu-latest + needs: static-analysis + + if: always() + + name: static-psalm-analysis-summary + + steps: + - name: Summary status + run: if ${{ needs.static-analysis.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b739a00..0e1db32f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,16 +18,16 @@ jobs: - i686-unknown-linux-musl - armv7-unknown-linux-musleabihf - aarch64-unknown-linux-musl + - x86_64-unknown-freebsd steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true target: ${{ matrix.target }} - - uses: Swatinem/rust-cache@v1 - uses: actions-rs/cargo@v1 with: use-cross: true @@ -41,39 +41,6 @@ jobs: asset_name: notify_push-${{ matrix.target }} tag: ${{ github.ref }} - package: - name: Package release - runs-on: ubuntu-20.04 - steps: - - name: musl-tools - run: | - sudo apt-get install musl-tools - - name: Checkout code - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: x86_64-unknown-linux-musl - - name: cross - run: | - cargo install cross - - name: Setup krankler - run: | - wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.0/krankerl - chmod +x krankerl - - name: Package app - run: | - ./krankerl package - - name: Upload binary to release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: build/artifacts/${{ env.APP_NAME }}.tar.gz - asset_name: ${{ env.APP_NAME }}.tar.gz - tag: ${{ github.ref }} - build-test-client: name: Build test client runs-on: ubuntu-20.04 @@ -82,14 +49,13 @@ jobs: - name: musl-tools run: | sudo apt-get install musl-tools - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true target: x86_64-unknown-linux-musl - - uses: Swatinem/rust-cache@v1 - run: cargo build --release --target x86_64-unknown-linux-musl working-directory: ./test_client - name: Upload binary to release diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 05a36ce4..34742bc7 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,26 +1,37 @@ -on: [push, pull_request] +name: Rust CI -name: CI +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read jobs: check: name: Check runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - - uses: Swatinem/rust-cache@v1 + target: x86_64-unknown-linux-musl + - uses: Swatinem/rust-cache@v2.2.0 - uses: actions-rs/cargo@v1 with: command: check build: - name: Build + name: Build release runs-on: ubuntu-20.04 + needs: check strategy: matrix: target: @@ -28,22 +39,25 @@ jobs: - i686-unknown-linux-musl - armv7-unknown-linux-musleabihf - aarch64-unknown-linux-musl - + - x86_64-unknown-freebsd + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true target: ${{ matrix.target }} - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2.2.0 + with: + key: ${{ matrix.target }} - uses: actions-rs/cargo@v1 with: use-cross: true command: build args: --release --target ${{ matrix.target }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: notify_push-${{ matrix.target }} path: target/${{ matrix.target }}/release/notify_push @@ -51,15 +65,16 @@ jobs: test: name: Tests runs-on: ubuntu-20.04 + needs: check steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2.2.0 - uses: actions-rs/cargo@v1 with: command: test @@ -72,17 +87,17 @@ jobs: - name: musl-tools run: | sudo apt-get install musl-tools - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true target: x86_64-unknown-linux-musl - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2.2.0 - run: cargo build --release --target x86_64-unknown-linux-musl working-directory: ./test_client - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: test_client path: target/x86_64-unknown-linux-musl/release/test_client @@ -90,14 +105,16 @@ jobs: msrv: name: Check MSRV runs-on: ubuntu-20.04 + needs: check steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.46 + toolchain: "1.60" override: true - - uses: Swatinem/rust-cache@v1 + target: x86_64-unknown-linux-musl + - uses: Swatinem/rust-cache@v2.2.0 - uses: actions-rs/cargo@v1 with: command: check diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index e04c9c9b..00000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Php Static analysis -on: [push, pull_request] - -jobs: - static-psalm-analysis: - runs-on: ubuntu-20.04 - strategy: - matrix: - ocp-version: [ 'dev-master' ] - name: Nextcloud ${{ matrix.ocp-version }} - steps: - - name: Checkout - uses: actions/checkout@master - - name: Set up php - uses: shivammathur/setup-php@master - with: - php-version: 7.4 - tools: composer:v1 - coverage: none - extensions: redis - - name: Install dependencies - run: composer i - - name: Install dependencies - run: composer require --dev christophwurst/nextcloud:${{ matrix.ocp-version }} - - name: Run coding standards check - run: composer run psalm diff --git a/.github/workflows/update-nextcloud-ocp.yml b/.github/workflows/update-nextcloud-ocp.yml new file mode 100644 index 00000000..e40744d3 --- /dev/null +++ b/.github/workflows/update-nextcloud-ocp.yml @@ -0,0 +1,83 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Update nextcloud/ocp + +on: + workflow_dispatch: + schedule: + - cron: "5 2 * * 0" + +jobs: + update-nextcloud-ocp: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + branches: ["main", "master", "stable27", "stable26", "stable25"] + + name: update-nextcloud-ocp-${{ matrix.branches }} + + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + ref: ${{ matrix.branches }} + submodules: true + + - name: Set up php8.1 + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: 8.1 + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Composer install + run: composer install + + - name: Composer update nextcloud/ocp + if: matrix.branches != 'main' + run: composer require --dev nextcloud/ocp:dev-${{ matrix.branches }} + + - name: Composer update nextcloud/ocp + if: matrix.branches == 'main' + run: composer require --dev nextcloud/ocp:dev-master + + - name: Reset checkout 3rdparty + run: | + git clean -f 3rdparty + git checkout 3rdparty + continue-on-error: true + + - name: Reset checkout vendor + run: | + git clean -f vendor + git checkout vendor + continue-on-error: true + + - name: Reset checkout vendor-bin + run: | + git clean -f vendor-bin + git checkout vendor-bin + continue-on-error: true + + - name: Create Pull Request + uses: peter-evans/create-pull-request@284f54f989303d2699d373481a0cfa13ad5a6666 # v3 + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + commit-message: "chore(dev-deps): Bump nextcloud/ocp package" + committer: GitHub + author: nextcloud-command + signoff: true + branch: automated/noid/${{ matrix.branches }}-update-nextcloud-ocp + title: "[${{ matrix.branches }}] Update nextcloud/ocp dependency" + body: | + Auto-generated update of [nextcloud/ocp](https://github.com/nextcloud-deps/ocp/) dependency + labels: | + dependencies + 3. to review diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 100% rename from .php_cs.dist rename to .php-cs-fixer.dist.php diff --git a/Cargo.lock b/Cargo.lock index fca9c5ce..22e33b95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.16.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -19,31 +19,43 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ - "getrandom 0.2.3", + "cfg-if", + "getrandom", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] -name = "ansi_term" -version = "0.11.0" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "winapi", + "libc", ] [[package]] @@ -55,42 +67,37 @@ dependencies = [ "winapi", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "async-stream" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.16", ] [[package]] @@ -104,9 +111,9 @@ dependencies = [ [[package]] name = "atoi" -version = "0.4.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" dependencies = [ "num-traits", ] @@ -117,28 +124,22 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] [[package]] name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - -[[package]] -name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -150,71 +151,58 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.12.3" +name = "backtrace-ext" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] -name = "beef" -version = "0.5.1" +name = "base64" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] -name = "bitflags" -version = "1.2.1" +name = "base64ct" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] -name = "bitvec" -version = "0.19.5" +name = "beef" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] -name = "block-buffer" -version = "0.9.0" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "buf_redux" -version = "0.8.4" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "memchr", - "safemem", + "generic-array", ] -[[package]] -name = "build_const" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" - [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byteorder" @@ -224,15 +212,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.69" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -242,112 +230,91 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ - "libc", + "iana-time-zone", "num-integer", "num-traits", - "time", "winapi", ] -[[package]] -name = "chunked_transfer" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" - [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", "bitflags", "strsim", - "textwrap", + "textwrap 0.11.0", "unicode-width", "vec_map", ] [[package]] -name = "color-eyre" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f1885697ee8a177096d42f158922251a41973117f6d8a234cee94b9509157b7" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] - -[[package]] -name = "color-spantrace" -version = "0.1.6" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6eee477a4a8a72f4addd4de416eb56d54bc307b284d6601bafdee1f4ea462d1" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", + "termcolor", + "unicode-width", ] [[package]] name = "combine" -version = "4.6.0" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d47c1b11006b87e492b53b313bb699ce60e16613c4dddaa91f8f7c220ab2fa" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ "bytes", - "futures-util", + "futures-core", "memchr", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] -name = "core-foundation" -version = "0.9.1" +name = "const-oid" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.1.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" +checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" dependencies = [ "libc", ] [[package]] name = "crc" -version = "1.8.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" dependencies = [ - "build_const", + "crc-catalog", ] +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + [[package]] name = "crc16" version = "0.4.0" @@ -355,20 +322,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff" [[package]] -name = "crossbeam-channel" -version = "0.5.1" +name = "crc32fast" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", - "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if", "crossbeam-utils", @@ -376,32 +342,105 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", - "lazy_static", ] [[package]] -name = "crypto-mac" -version = "0.10.1" +name = "crypto-bigint" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" dependencies = [ "generic-array", "subtle", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cxx" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.16", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] + [[package]] name = "dashmap" -version = "4.0.2" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if", - "num_cpus", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core 0.9.7", +] + +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", + "crypto-bigint", + "pem-rfc7468", ] [[package]] @@ -412,32 +451,34 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "digest" -version = "0.9.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "generic-array", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] name = "dirs" -version = "3.0.2" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -451,50 +492,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] -name = "dtoa" -version = "0.4.8" +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "either" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if", ] [[package]] -name = "eyre" -version = "0.6.5" +name = "errno" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ - "indenter", - "once_cell", + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", ] [[package]] name = "flexi_logger" -version = "0.18.0" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba2265890613939b533fa11c3728651531419ac549ccf527896201581f23991" +checksum = "6eae57842a8221ef13f1f207632d786a175dd13bd8fbdc8be9d852f7c9cf1046" dependencies = [ - "atty", "chrono", "glob", + "is-terminal", "lazy_static", "log", + "nu-ansi-term", "regex", "thiserror", - "yansi", +] + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.6", ] [[package]] @@ -505,25 +585,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "futures" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -536,9 +609,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -546,59 +619,67 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + [[package]] name = "futures-io" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 2.0.16", ] [[package]] name = "futures-sink" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.16" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -608,16 +689,14 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -625,43 +704,32 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "gimli" -version = "0.25.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.3" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" dependencies = [ "bytes", "fnv", @@ -678,36 +746,36 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] name = "hashlink" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ "hashbrown", ] [[package]] name = "headers" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bitflags", "bytes", "headers-core", "http", + "httpdate", "mime", - "sha-1", - "time", + "sha1", ] [[package]] @@ -728,6 +796,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -737,27 +814,50 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" -version = "0.10.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "crypto-mac", "digest", ] [[package]] name = "http" -version = "0.2.4" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", @@ -766,18 +866,18 @@ dependencies = [ [[package]] name = "http-auth-basic" -version = "0.2.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "798bcfc10d720c1c704171dc40bc2cdf8f37445e3f5a7fdc3cfe8140a833bc4a" +checksum = "dd2e17aacf7f4a2428def798e2ff4f4f883c0987bdaf47dd5c8bc027bc9f1ebc" dependencies = [ - "base64 0.12.3", + "base64 0.13.1", ] [[package]] name = "http-body" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -786,21 +886,21 @@ dependencies = [ [[package]] name = "httparse" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.11" +version = "0.14.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" dependencies = [ "bytes", "futures-channel", @@ -822,81 +922,125 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ - "futures-util", + "http", "hyper", - "log", - "rustls", + "rustls 0.20.8", "tokio", "tokio-rustls", - "webpki", ] [[package]] -name = "idna" -version = "0.2.3" +name = "iana-time-zone" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", ] [[package]] -name = "indenter" -version = "0.3.3" +name = "iana-time-zone-haiku" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] [[package]] -name = "indexmap" -version = "1.7.0" +name = "idna" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "autocfg 1.0.1", - "hashbrown", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "input_buffer" -version = "0.4.0" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "bytes", + "autocfg", + "hashbrown", ] [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "ipnet" -version = "2.3.1" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + +[[package]] +name = "is-terminal" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "is_ci" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -907,93 +1051,89 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", -] - -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", + "spin 0.5.2", ] [[package]] name = "libc" -version = "0.2.98" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] name = "libm" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libsqlite3-sys" -version = "0.22.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" dependencies = [ "cc", "pkg-config", "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "logos" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427e2abca5be13136da9afdbf874e6b34ad9001dd70f2b103b083a85daa7b345" +checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" dependencies = [ "logos-derive", ] [[package]] name = "logos-derive" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d" +checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" dependencies = [ "beef", "fnv", "proc-macro2", "quote", "regex-syntax", - "syn", - "utf8-ranges", + "syn 1.0.109", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matchers" version = "0.0.1" @@ -1003,40 +1143,64 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "block-buffer", "digest", - "opaque-debug", ] [[package]] name = "memchr" -version = "2.4.0" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miette" +version = "5.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a992891d5579caa9efd8e601f82e30a1caa79a27a5db075dde30ecb9eab357" +dependencies = [ + "backtrace", + "backtrace-ext", + "is-terminal", + "miette-derive", + "once_cell", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap 0.15.2", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "4c65c625186a9bcce6699394bee511e1b1aec689aa7e3be1bf4e996e75834153" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -1059,62 +1223,58 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", - "autocfg 1.0.1", ] [[package]] name = "mio" -version = "0.7.13" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi", + "windows-sys 0.45.0", ] [[package]] -name = "multipart" -version = "0.17.1" +name = "multer" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050aeedc89243f5347c3e237e3e13dc76fbe4ae3742a57b94dc14f69acf76d4" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "buf_redux", + "bytes", + "encoding_rs", + "futures-util", + "http", "httparse", "log", + "memchr", "mime", - "mime_guess", - "quick-error", - "rand 0.7.3", - "safemem", - "tempfile", - "twoway", + "spin 0.9.6", + "version_check", ] [[package]] name = "nextcloud-config-parser" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22926379c3188875dde6295306244695f5f897173ee9568f110e6b3e280a067" +checksum = "e49543396f56a4b6e270601f7da68760acd9dc8c3bf000ae430d22e63325f0a4" dependencies = [ + "miette", "php-literal-parser", "redis", "sqlx", @@ -1134,23 +1294,19 @@ dependencies = [ [[package]] name = "nom" -version = "6.1.2" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "bitvec", - "funty", - "lexical-core", "memchr", - "version_check", + "minimal-lexical", ] [[package]] name = "notify_push" version = "0.1.0" dependencies = [ - "ahash", - "color-eyre", + "ahash 0.8.3", "dashmap", "derivative", "dotenv", @@ -1158,13 +1314,14 @@ dependencies = [ "futures", "http-auth-basic", "log", + "miette", "mini-redis", "nextcloud-config-parser", "nextcloud_appinfo", "once_cell", "parse-display", "percent-encoding", - "rand 0.8.4", + "rand", "redis", "reqwest", "serde", @@ -1176,156 +1333,144 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", - "tokio-tungstenite 0.15.0", + "tokio-tungstenite 0.19.0", + "url", "warp", "warp-real-ip", ] [[package]] -name = "ntapi" -version = "0.3.6" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ + "overload", "winapi", ] [[package]] name = "num-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" -dependencies = [ - "autocfg 1.0.1", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-bigint-dig" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4547ee5541c18742396ae2c895d0717d0f886d8823b8399cdaf7b07d63ad0480" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" dependencies = [ - "autocfg 0.1.7", "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", - "rand 0.8.4", + "rand", "smallvec", "zeroize", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.0.1", + "autocfg", "libm", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" - [[package]] name = "object" -version = "0.26.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] -name = "openssl-probe" -version = "0.1.4" +name = "owo-colors" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] -name = "owo-colors" -version = "1.3.0" +name = "parking_lot" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if", "instant", @@ -1335,11 +1480,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + [[package]] name = "parse-display" -version = "0.5.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17011e14e6b831ed3aeab847a62fd338aee88539fcc99f23ce5ba98feba328" +checksum = "6f96cc033d72896bb9a2c239a14e1141c3e2eae6d649e7c10ef4e598d66bc86c" dependencies = [ "once_cell", "parse-display-derive", @@ -1348,9 +1506,9 @@ dependencies = [ [[package]] name = "parse-display-derive" -version = "0.5.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad30302271e65d661910580baf25e874cd92c4595ddbed74d1ec9b2fdfaae64b" +checksum = "e5587062be441f3d868f7c4c9d13c67f286b03aa679d7f8176ef80bf2ee79e5d" dependencies = [ "once_cell", "proc-macro2", @@ -1358,25 +1516,29 @@ dependencies = [ "regex", "regex-syntax", "structmeta", - "syn", + "syn 1.0.109", ] [[package]] -name = "pem" -version = "0.8.3" +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "pem-rfc7468" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30" dependencies = [ - "base64 0.13.0", - "once_cell", - "regex", + "base64ct", ] [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "peresil" @@ -1386,42 +1548,43 @@ checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" [[package]] name = "php-literal-parser" -version = "0.2.10" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ae2f1814c909bc6d2e1ba26eacbb3d451f292814774413e0c7f83b9bd3a3c0" +checksum = "aae9b58aaf3fdcc2970e0c98e9ff8c5865cfd2c165371007d0a7771dc79c3d93" dependencies = [ "logos", "memchr", + "miette", + "parse-display", "serde", - "source-span", "thiserror", ] [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1429,17 +1592,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320" +dependencies = [ + "der", + "pkcs8", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-error" @@ -1450,7 +1635,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -1465,25 +1650,13 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1494,52 +1667,22 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.9" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -1549,62 +1692,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "rand_core 0.6.3", + "getrandom", ] [[package]] name = "redis" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbc1838d8d0b423f325d6fac80c5f19109c7d16c8c37c584893dc17cf71c63d" +checksum = "3ea8c51b5dc1d8e5fd3350ec8167f464ec0995e79f2e90a075b63371500d557f" dependencies = [ "async-trait", "bytes", "combine", "crc16", - "dtoa", "futures-util", "itoa", "percent-encoding", "pin-project-lite", - "rand 0.8.4", - "sha1", + "rand", + "ryu", + "sha1_smol", "tokio", "tokio-util", "url", @@ -1612,37 +1728,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] -[[package]] -name = "redox_termios" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" -dependencies = [ - "redox_syscall", -] - [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.3", + "getrandom", "redox_syscall", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", @@ -1660,52 +1768,46 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" -version = "0.11.4" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" +checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ - "base64 0.13.0", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", "hyper-rustls", "ipnet", "js-sys", - "lazy_static", "log", "mime", + "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.20.8", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-rustls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.22.6", "winreg", ] @@ -1727,7 +1829,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -1735,37 +1837,50 @@ dependencies = [ [[package]] name = "rsa" -version = "0.4.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0aeddcca1082112a6eeb43bf25fd7820b066aaf6eaef776e19d0a1febe38fe" +checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" dependencies = [ "byteorder", "digest", - "lazy_static", "num-bigint-dig", "num-integer", "num-iter", "num-traits", - "pem", - "rand 0.8.4", - "simple_asn1", + "pkcs1", + "pkcs8", + "rand_core", + "smallvec", "subtle", "zeroize", ] [[package]] name = "rustc-demangle" -version = "0.1.20" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + +[[package]] +name = "rustix" +version = "0.36.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" +checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] [[package]] name = "rustls" -version = "0.19.1" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ - "base64 0.13.0", "log", "ring", "sct", @@ -1773,44 +1888,47 @@ dependencies = [ ] [[package]] -name = "rustls-native-certs" -version = "0.5.0" +name = "rustls" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" dependencies = [ - "openssl-probe", - "rustls", - "schannel", - "security-framework", + "log", + "ring", + "rustls-webpki", + "sct", ] [[package]] -name = "ryu" -version = "1.0.5" +name = "rustls-pemfile" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.0", +] [[package]] -name = "safemem" -version = "0.3.3" +name = "rustls-webpki" +version = "0.100.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] [[package]] -name = "schannel" -version = "0.1.19" +name = "ryu" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi", -] +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -1819,36 +1937,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "security-framework" -version = "2.3.1" +name = "scratch" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] -name = "security-framework-sys" -version = "2.3.0" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "core-foundation-sys", - "libc", + "ring", + "untrusted", ] [[package]] @@ -1868,29 +1969,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.126" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.16", ] [[package]] name = "serde_json" -version = "1.0.66" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -1899,9 +2000,9 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", @@ -1910,122 +2011,126 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.9.7" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "block-buffer", "cfg-if", "cpufeatures", "digest", - "opaque-debug", ] [[package]] -name = "sha1" -version = "0.6.0" +name = "sha1_smol" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sha2" -version = "0.9.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ - "block-buffer", "cfg-if", "cpufeatures", "digest", - "opaque-debug", ] [[package]] name = "sharded-slab" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ "lazy_static", ] [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] -name = "simple_asn1" -version = "0.5.4" +name = "slab" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb4ea60fb301dc81dfc113df680571045d375ab7345d171c5dc7d7e13107a80" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ - "chrono", - "num-bigint 0.4.0", - "num-traits", - "thiserror", + "autocfg", ] [[package]] -name = "slab" -version = "0.4.3" +name = "smallvec" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +dependencies = [ + "serde", +] [[package]] -name = "smallvec" -version = "1.6.1" +name = "smawk" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" [[package]] name = "socket2" -version = "0.4.1" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", ] [[package]] -name = "source-span" -version = "2.2.1" +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3792c323741d487c9a51ade42130f202567f6bba0a21c3b536f1e260d1e9d1" +checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34" dependencies = [ - "termion", + "lock_api", ] [[package]] -name = "spin" -version = "0.5.2" +name = "spki" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] [[package]] name = "sqlformat" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d86e3c77ff882a828346ba401a7ef4b8e440df804491c6064fe8295765de71c" +checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" dependencies = [ - "lazy_static", - "maplit", + "itertools", "nom", - "regex", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba82f79b31f30acebf19905bcd8b978f46891b9d0723f578447361a8910b6584" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2033,46 +2138,52 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f23af36748ec8ea8d49ef8499839907be41b0b1178a4e82b8cb45d29f531dc9" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ - "ahash", - "atoi 0.4.0", - "base64 0.13.0", + "ahash 0.7.6", + "atoi 1.0.0", + "base64 0.13.1", "bitflags", "byteorder", "bytes", "crc", - "crossbeam-channel", "crossbeam-queue", - "crossbeam-utils", "digest", "dirs", + "dotenvy", "either", + "event-listener", + "flume", "futures-channel", "futures-core", + "futures-executor", + "futures-intrusive", "futures-util", "generic-array", "hashlink", "hex", + "hkdf", "hmac", + "indexmap", "itoa", "libc", "libsqlite3-sys", "log", "md-5", "memchr", - "num-bigint 0.3.2", + "num-bigint", "once_cell", - "parking_lot", + "paste", "percent-encoding", - "rand 0.8.4", + "rand", "rsa", - "rustls", + "rustls 0.20.8", + "rustls-pemfile", "serde", "serde_json", - "sha-1", + "sha1", "sha2", "smallvec", "sqlformat", @@ -2081,48 +2192,40 @@ dependencies = [ "thiserror", "tokio-stream", "url", - "webpki", - "webpki-roots", + "webpki-roots 0.22.6", "whoami", ] [[package]] name = "sqlx-macros" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4a2349d1ffd60a03ca0de3f116ba55d7f406e55a0d84c64a5590866d94c06" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" dependencies = [ - "dotenv", + "dotenvy", "either", - "futures", - "heck", + "heck 0.4.1", "once_cell", "proc-macro2", "quote", "sha2", "sqlx-core", "sqlx-rt", - "syn", + "syn 1.0.109", "url", ] [[package]] name = "sqlx-rt" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8199b421ecf3493ee9ef3e7bc90c904844cfb2ea7ea2f57347a93f52bfd3e057" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" dependencies = [ "once_cell", "tokio", "tokio-rustls", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stringprep" version = "0.1.2" @@ -2141,32 +2244,32 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structmeta" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55b4052fd036e3d1fe74ea978426a3f87997ba803e7a8e69ff0cf99f35a720a" +checksum = "104842d6278bf64aa9d2f182ba4bde31e8aec7a131d29b7f444bb9b344a09e2a" dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn", + "syn 1.0.109", ] [[package]] name = "structmeta-derive" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55502dda4b5fd26b33f6810d7493b4f5d7859bca604bd07ff22a523cd257ee" +checksum = "24420be405b590e2d746d83b01f09af673270cf80e9b003a5fa7b651c58c7d93" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "structopt" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -2175,15 +2278,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2192,6 +2295,34 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "supports-color" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" +dependencies = [ + "is-terminal", + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4806e0b03b9906e76b018a5d821ebf198c8e9dc0829ed3328eeeb5094aed60" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "supports-unicode" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" +dependencies = [ + "is-terminal", +] + [[package]] name = "sxd-document" version = "0.3.2" @@ -2215,70 +2346,57 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.74" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] -name = "synstructure" -version = "0.12.5" +name = "syn" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", - "syn", - "unicode-xid", + "unicode-ident", ] [[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.2.0" +name = "termcolor" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ - "cfg-if", - "libc", - "rand 0.8.4", - "redox_syscall", - "remove_dir_all", - "winapi", + "winapi-util", ] [[package]] -name = "termion" -version = "1.5.6" +name = "terminal_size" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ "libc", - "numtoa", - "redox_syscall", - "redox_termios", + "winapi", ] [[package]] name = "test_client" version = "0.1.0" dependencies = [ - "base64 0.13.0", - "color-eyre", + "base64 0.21.0", "flexi_logger", "log", + "miette", "serde_json", - "tungstenite 0.14.0", + "tungstenite 0.19.0", "ureq", + "url", ] [[package]] @@ -2290,107 +2408,108 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.16", ] [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.9.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" dependencies = [ - "autocfg 1.0.1", + "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", - "once_cell", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", + "socket2", "tokio-macros", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.16", ] [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls", + "rustls 0.20.8", "tokio", "webpki", ] [[package]] name = "tokio-stream" -version = "0.1.7" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -2399,55 +2518,53 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.13.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" dependencies = [ "futures-util", "log", - "pin-project", "tokio", - "tungstenite 0.12.0", + "tungstenite 0.18.0", ] [[package]] name = "tokio-tungstenite" -version = "0.15.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" dependencies = [ "futures-util", "log", - "pin-project", "tokio", - "tungstenite 0.14.0", + "tungstenite 0.19.0", ] [[package]] name = "tokio-util" -version = "0.6.7" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", @@ -2458,32 +2575,23 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "tracing-core" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-error" -version = "0.1.2" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "tracing", - "tracing-subscriber", + "once_cell", + "valuable", ] [[package]] @@ -2498,9 +2606,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", @@ -2509,9 +2617,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", "tracing-core", @@ -2519,11 +2627,11 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.19" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "chrono", "lazy_static", "matchers", @@ -2541,58 +2649,49 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.12.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "byteorder", "bytes", "http", "httparse", - "input_buffer", "log", - "rand 0.8.4", - "sha-1", + "rand", + "sha1", + "thiserror", "url", "utf-8", ] [[package]] name = "tungstenite" -version = "0.14.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" dependencies = [ - "base64 0.13.0", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", - "rand 0.8.4", - "rustls", - "rustls-native-certs", - "sha-1", + "rand", + "rustls 0.21.1", + "sha1", "thiserror", "url", "utf-8", "webpki", -] - -[[package]] -name = "twoway" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" -dependencies = [ - "memchr", + "webpki-roots 0.23.0", ] [[package]] @@ -2603,15 +2702,15 @@ checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" [[package]] name = "typenum" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "uncased" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" dependencies = [ "version_check", ] @@ -2627,39 +2726,46 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-linebreak" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" +checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" dependencies = [ - "matches", + "hashbrown", + "regex", ] [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.2" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode_categories" @@ -2675,29 +2781,28 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.1.1" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2475a6781e9bc546e7b64f4013d2f4032c8c6a40fcffd7c6f4ee734a890972ab" +checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" dependencies = [ - "base64 0.13.0", - "chunked_transfer", + "base64 0.13.1", + "flate2", "log", "once_cell", - "rustls", + "rustls 0.20.8", "url", "webpki", - "webpki-roots", + "webpki-roots 0.22.6", ] [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -2708,10 +2813,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] -name = "utf8-ranges" -version = "1.0.4" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -2727,9 +2832,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" @@ -2743,28 +2848,31 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" +checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" dependencies = [ "bytes", - "futures", + "futures-channel", + "futures-util", "headers", "http", "hyper", "log", "mime", "mime_guess", - "multipart", + "multer", "percent-encoding", "pin-project", + "rustls-pemfile", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", + "tokio-rustls", "tokio-stream", - "tokio-tungstenite 0.13.0", + "tokio-tungstenite 0.18.0", "tokio-util", "tower-service", "tracing", @@ -2782,48 +2890,40 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", - "serde", - "serde_json", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.24" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if", "js-sys", @@ -2833,9 +2933,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2843,28 +2943,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -2872,9 +2972,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.4" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", "untrusted", @@ -2882,18 +2982,27 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.21.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ "webpki", ] +[[package]] +name = "webpki-roots" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa54963694b65584e170cf5dc46aeb4dcaa5584e652ff5f3952e56d66aff0125" +dependencies = [ + "rustls-webpki", +] + [[package]] name = "whoami" -version = "1.1.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abacf325c958dfeaf1046931d37f2a901b6dfe0968ee965a29e94c6766b2af6" +checksum = "2c70234412ca409cc04e864e89523cb0fc37f5e1344ebed5a3ebf4192b6b9f68" dependencies = [ "wasm-bindgen", "web-sys", @@ -2915,6 +3024,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2922,53 +3040,167 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "winreg" -version = "0.7.0" +name = "windows" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" dependencies = [ - "winapi", + "windows-targets 0.42.2", ] [[package]] -name = "wyz" -version = "0.2.0" +name = "windows-sys" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] [[package]] -name = "xpath_reader" -version = "0.5.3" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6d1ee2e32707ac4e378220b26b0de8d8c11288da9ab86f7a97d277cb7ce0c9" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "sxd-document", - "sxd-xpath", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] -name = "yansi" -version = "0.5.0" +name = "windows-targets" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] [[package]] -name = "zeroize" -version = "1.3.0" +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winreg" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "zeroize_derive", + "winapi", ] [[package]] -name = "zeroize_derive" -version = "1.1.0" +name = "xpath_reader" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" +checksum = "eb6d1ee2e32707ac4e378220b26b0de8d8c11288da9ab86f7a97d277cb7ce0c9" dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", + "sxd-document", + "sxd-xpath", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index f7c9b522..a07113b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,42 +3,44 @@ name = "notify_push" version = "0.1.0" # this version number is unused, the version number for the binary will be extracted from the appinfo/info.xml during build authors = ["Robin Appelman "] edition = "2018" +rust-version = "1.60" [dependencies] -redis = { version = "0.21", features = ["tokio-comp", "aio", "cluster"] } -serde = { version = "1", features = ["derive"] } -serde_json = "1" -thiserror = "1" -warp = "0.3" -tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] } -futures = "0.3" -log = "0.4" -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "any", "macros", "mysql", "sqlite", "postgres"] } -dotenv = "0.15" -dashmap = "4" -once_cell = "1" -color-eyre = "0.5" -smallvec = "1" -reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "json"] } -warp-real-ip = "0.2" -parse-display = "0.5" -percent-encoding = "2" -rand = "0.8" -ahash = "0.7" -flexi_logger = { version = "0.18", features = ["colors"] } -tokio-stream = { version = "0.1", features = ["net"] } -structopt = "0.3" -derivative = "2" -nextcloud-config-parser = { version = "0.4", features = ["db-sqlx", "redis-connect"] } +redis = { version = "0.23.0", features = ["tokio-comp", "aio", "cluster"] } +serde = { version = "1.0.163", features = ["derive"] } +serde_json = "1.0.96" +thiserror = "1.0.40" +warp = { version = "0.3.5", features = ["tls"] } +tokio = { version = "1.28.1", features = ["macros", "rt-multi-thread", "signal"] } +futures = "0.3.28" +log = "0.4.17" +sqlx = { version = "0.6.3", features = ["runtime-tokio-rustls", "any", "macros", "mysql", "sqlite", "postgres"] } +dotenv = "0.15.0" +dashmap = "5.4.0" +once_cell = "1.17.1" +miette = { version = "5.8.0", features = ["fancy"] } +smallvec = { version = "1.10.0", features = ["serde"] } +reqwest = { version = "0.11.17", default-features = false, features = ["rustls-tls", "json"] } +warp-real-ip = "0.2.0" +parse-display = "0.8.0" +percent-encoding = "2.2.0" +rand = "0.8.5" +ahash = "0.8.3" +flexi_logger = { version = "=0.25.3", features = ["colors", "is-terminal"] } +tokio-stream = { version = "0.1.14", features = ["net"] } +structopt = "0.3.26" +derivative = "2.2.0" +nextcloud-config-parser = { version = "0.8.0", features = ["db-sqlx", "redis-connect"] } +url = "2.3.1" [dev-dependencies] -mini-redis = "0.4" -tokio-tungstenite = "0.15" -http-auth-basic = "0.2" +mini-redis = "0.4.1" +tokio-tungstenite = "0.19.0" +http-auth-basic = "0.3.3" test_client = { path = "test_client" } [build-dependencies] -nextcloud_appinfo = "0.6" +nextcloud_appinfo = "0.6.0" [profile.dev.package.backtrace] opt-level = 3 @@ -46,8 +48,4 @@ opt-level = 3 [profile.release] lto = true -[features] -default = ["span-colors"] -span-colors = ["nextcloud-config-parser/span-colors"] - -[workspace] \ No newline at end of file +[workspace] diff --git a/DEVELOPING.md b/DEVELOPING.md index ab27fd74..6d5c3abc 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -36,6 +36,10 @@ Desktop and other clients that don't run in the Nextcloud web interface can use - "notify_activity" when a new activity item for a user is created (note, due to workings of the activity app, file related activity doesn't trigger this notification) - "notify_notification" when a notification is created, processed or dismissed for a user +- Starting with version 0.4 you can opt into receiving the changed file ids for file update notifications by sending `listen notify_file_id` over the websocket. + Once enabled, the server will send "notify_file_id" followed by a json encoded array of file ids if the push server knows + the ids of the changed files. + In cases where there push server doesn't know which files have changed, it will send the regular "notify_file" message. ### Example @@ -114,7 +118,7 @@ listen('my_message_type', (message_type, optional_body) => { ## Building -The server binary is built using rust and cargo, and requires a minimum of rust `1.46`. +The server binary is built using rust and cargo, and requires a minimum of rust `1.60`. - Install `rust` through your package manager or [rustup](https://rustup.rs/) - Run `cargo build` diff --git a/Dockerfile b/Dockerfile index c2ddc9a5..93e1417a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,9 @@ -FROM ekidd/rust-musl-builder AS build +FROM clux/muslrust:stable AS build COPY Cargo.toml Cargo.lock ./ # Build with a dummy main to pre-build dependencies RUN mkdir src && \ - sudo chown -R rust:rust . && \ sed -i '/test_client/d' Cargo.toml && \ echo "fn main(){}" > src/main.rs && \ cargo build --release && \ @@ -13,13 +12,13 @@ RUN mkdir src && \ COPY build.rs ./ COPY appinfo/info.xml ./appinfo/ COPY src/ ./src/ -RUN sudo chown -R rust:rust . && touch src/main.rs +RUN touch src/main.rs RUN cargo build --release FROM scratch -COPY --from=build /home/rust/src/target/x86_64-unknown-linux-musl/release/notify_push / +COPY --from=build /volume/target/x86_64-unknown-linux-musl/release/notify_push / EXPOSE 7867 ENTRYPOINT ["/notify_push"] diff --git a/README.md b/README.md index 1b370244..7a62cc5a 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ With many clients all checking for updates a large portion of the server load ca By providing a way for the server to send update notifications to the clients, the need for the clients to make these checks can be greatly reduced. -Update notifications are provided on a "best effort" basis, updates might happen without a notification being send and a -notification can be send even if no update has actually happened. Clients are advised to still perform periodic checks +Update notifications are provided on a "best effort" basis, updates might happen without a notification being sent and a +notification can be sent even if no update has actually happened. Clients are advised to still perform periodic checks for updates on their own, although these can be run on a much lower frequency. ## Requirements @@ -40,13 +40,13 @@ The setup required consists of three steps ### Push server -#### Setting up the service +The push server should be setup to run as a background daemon, the recommended way is by setting it up as a system service in the init system. +If you're not using systemd then any init or process management system that runs the push server binary with the described environment variables will work. -The push server should be setup to run as a background daemon, the recommended way is by setting up a systemd service to -run the server. If you're not using systemd than any init or process management system that runs the push server binary -with the described environment variables will work. +#### systemd -You can create a systemd service by creating a file named `/etc/systemd/system/notify_push.service` with the following + +For systemd based setups, you can create a systemd service by creating a file named `/etc/systemd/system/notify_push.service` with the following content. ```ini @@ -63,8 +63,6 @@ User=www-data WantedBy = multi-user.target ``` -Adjusting the paths and ports as needed. -
Snap configuration (click to expand) @@ -76,8 +74,8 @@ Description = Push daemon for Nextcloud clients [Service] Environment=PORT=7867 # Change if you already have something running on this port -Environment=DATABASE_URL=mysql://nextcloud:CHANGEME@localhost/nextcloud?socket=/tmp/snap.nextcloud/tmp/sockets/mysql.sock -Environment=REDIS_URL=redis+unix:///tmp/snap.nextcloud/tmp/sockets/redis.sock +Environment=DATABASE_URL=mysql://nextcloud:CHANGEME@localhost/nextcloud?socket=/tmp/snap-private-tmp/snap.nextcloud/tmp/sockets/mysql.sock +Environment=REDIS_URL=redis+unix:///tmp/snap-private-tmp/snap.nextcloud/tmp/sockets/redis.sock ExecStart=/var/snap/nextcloud/current/nextcloud/extra-apps/notify_push/bin/x86_64/notify_push /var/snap/nextcloud/current/nextcloud/config/config.php User=root @@ -87,15 +85,43 @@ WantedBy = multi-user.target
+#### OpenRC + +For OpenRC based setups, you can create an OpenRC service by creating a file named `/etc/init.d/notify_push` with the following content. + +```sh +#!/sbin/openrc-run + +description="Push daemon for Nextcloud clients" + +output_log=${output_log:-/var/log/$RC_SVCNAME.log} +pidfile=${pidfile:-/run/$RC_SVCNAME.pid} + +command=${command:-/path/to/push/binary/notify_push} +command_user=${command_user:-www-data:www-data} +command_args="--port 7867 /path/to/nextcloud/config/config.php" +command_background=true + +depend() { + need net redis + use nginx php-fpm8 mariadb postgresql +} + +start_pre() { + checkpath --file --owner $command_user $output_log +} +``` + +Adjust the paths, ports and user as needed. + + #### Configuration -The push server can be configured either by loading the config from the nextcloud `config.php` -or by setting all options through environment variables. +The push server can be configured either by loading the config from the nextcloud `config.php` or by setting all options through environment variables. Re-using the configuration from nextcloud is the recommended way, as it ensures that the configuration remains in sync. -If using the `config.php` isn't possible, you can configure the push server by setting the following environment -variables: +If using the `config.php` isn't possible, you can configure the push server by setting the following environment variables: - `DATABASE_URL` connection url for the Nextcloud database, e.g. `postgres://user:password@db_host/db_name` - `DATABASE_PREFIX` database prefix configured in Nextcloud, e.g. `oc_` @@ -113,19 +139,31 @@ Alternatively you can configure the server to listen on a unix socket by setting Note that Nextcloud load all files matching `*.config.php` in the config directory in additional to the main config file. You can enable this same behavior by passing the `--glob-config` option. +#### TLS Configuration + +The push server can be configured to serve over TLS. This is mostly intended for securing the traffic between the push server +and the reverse proxy if they are running on different hosts, running without a reverse proxy (or load balancer) is not recommended. + +TLS can be enabled by setting the `--tls-cert` and `--tls-key` arguments (or the `TLS_CERT` and `TLS_KEY` environment variables). + #### Starting the service Once the systemd service file is set up with the correct configuration you can start it using -`sudo systemctl start notify_push` +- systemd: `sudo systemctl start notify_push` +- OpenRc: `sudo rc-service notify_push start` and enable it to automatically start on boot using -`sudo systemctl enable notify_push` +- systemd: `sudo systemctl enable notify_push` +- OpenRc: `sudo rc-update add notify_push` + Every time this app receives an update you should restart the systemd service using -`sudo systemctl restart notify_push` +- systemd: `sudo systemctl restart notify_push` +- OpenRc: `sudo rc-service notify_push restart` +
Alternatively, you can do this automatically via systemctl by creating the following systemd service and path (click to expand) @@ -236,7 +274,7 @@ sudo systemctl restart apache2 ```Caddyfile route /push/* { uri strip_prefix /push - reverse_proxy http://127.0.0.1:7867/ + reverse_proxy http://127.0.0.1:7867 } ``` @@ -300,8 +338,8 @@ For information about how to use the push server in your own app or client, see ## Test client For development and testing purposes a test client is provided which can be downloaded from -the [github actions](https://github.com/nextcloud/notify_push/actions/workflows/rust.yml) page.
-(Click on a run from the list, scroll to the bottom and click on `test_client` to download the binary.)
+the [current release](https://github.com/nextcloud/notify_push/releases/latest) page.
+(Click on `test_client` to download the binary.)
Please note: the Test client is only build for x86_64 Linux currently. ```bash diff --git a/appinfo/info.xml b/appinfo/info.xml index 1da7ca94..d535fa09 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -7,7 +7,7 @@ - 0.2.2 + 0.6.3 agpl Robin Appelman NotifyPush @@ -23,7 +23,7 @@ Once the app is installed, the push binary needs to be setup. You can either use https://github.com/nextcloud/notify_push/issues - + @@ -40,5 +40,6 @@ Once the app is installed, the push binary needs to be setup. You can either use OCA\NotifyPush\Command\SelfTest OCA\NotifyPush\Command\Log OCA\NotifyPush\Command\Metrics + OCA\NotifyPush\Command\Reset diff --git a/composer.json b/composer.json index 64708d6b..70ee30ba 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,28 @@ { - "name": "nextcloud/text", - "type": "project", - "require-dev": { - "roave/security-advisories": "dev-master", - "christophwurst/nextcloud": "dev-master", - "php-parallel-lint/php-parallel-lint": "^1.0.0", - "nextcloud/coding-standard": "^0.4.0", - "psalm/phar": "^4.3" - }, - "license": "AGPLv3", - "authors": [ - { - "name": "Julius Härtl", - "email": "jus@bitgrid.net" - } - ], - "require": {}, - "scripts": { - "lint": "parallel-lint --exclude src --exclude vendor --exclude target --exclude build .", - "cs:check": "php-cs-fixer fix --dry-run --diff", - "cs:fix": "php-cs-fixer fix", - "psalm": "psalm.phar" - } + "name": "nextcloud/text", + "type": "project", + "require-dev": { + "roave/security-advisories": "dev-master", + "php-parallel-lint/php-parallel-lint": "^1.0.0", + "phpunit/phpunit": "^8", + "nextcloud/coding-standard": "^v1.1.1", + "nextcloud/ocp": "dev-master", + "psalm/phar": "^4.3", + "symfony/console": "5.4.19" + }, + "license": "AGPLv3", + "authors": [ + { + "name": "Julius Härtl", + "email": "jus@bitgrid.net" + } + ], + "require": {}, + "scripts": { + "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './build/*' -not -path './tests/integration/vendor/*' -print0 | xargs -0 -n1 php -l", + "cs:check": "php-cs-fixer fix --dry-run --diff", + "cs:fix": "php-cs-fixer fix", + "test:unit": "phpunit -c tests/phpunit.xml", + "psalm": "psalm.phar" + } } diff --git a/composer.lock b/composer.lock index 77da3ae8..4f4486d4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,80 +4,40 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ff4986269c4a13698501b21f622804b6", + "content-hash": "53adf596e7248d85adffe83517718b0b", "packages": [], "packages-dev": [ { - "name": "christophwurst/nextcloud", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/ChristophWurst/nextcloud_composer.git", - "reference": "e584400fc2614608cfb57231ca4fde7eafb81afd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/e584400fc2614608cfb57231ca4fde7eafb81afd", - "reference": "e584400fc2614608cfb57231ca4fde7eafb81afd", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "22.0.0-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" - } - ], - "description": "Composer package containing Nextcloud's public API (classes, interfaces)", - "support": { - "issues": "https://github.com/ChristophWurst/nextcloud_composer/issues", - "source": "https://github.com/ChristophWurst/nextcloud_composer/tree/master" - }, - "time": "2021-02-11T00:20:09+00:00" - }, - { - "name": "composer/semver", - "version": "3.2.4", + "name": "doctrine/instantiator", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -86,146 +46,118 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "constructor", + "instantiate" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.4" + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { - "url": "https://packagist.com", + "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { - "url": "https://github.com/composer", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", "type": "tidelift" } ], - "time": "2020-11-13T08:59:24+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { - "name": "composer/xdebug-handler", - "version": "1.4.5", + "name": "myclabs/deep-copy", + "version": "1.11.1", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "f28d44c286812c714741478d968104c5e604a1d4" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4", - "reference": "f28d44c286812c714741478d968104c5e604a1d4", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "Composer\\XdebugHandler\\": "src" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "Xdebug", - "performance" + "clone", + "copy", + "duplicate", + "object", + "object graph" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/1.4.5" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-11-13T08:04:11+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { - "name": "doctrine/annotations", - "version": "1.11.1", + "name": "nextcloud/coding-standard", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "ce77a7ba1770462cd705a91a151b6c3746f9c6ad" + "url": "https://github.com/nextcloud/coding-standard.git", + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/ce77a7ba1770462cd705a91a151b6c3746f9c6ad", - "reference": "ce77a7ba1770462cd705a91a151b6c3746f9c6ad", + "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/55def702fb9a37a219511e1d8c6fe8e37164c1fb", + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/cache": "1.*", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^9.1.5" + "php": "^7.3|^8.0", + "php-cs-fixer/shim": "^3.17" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + "Nextcloud\\CodingStandard\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -234,335 +166,242 @@ ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" } ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], + "description": "Nextcloud coding standards for the php cs fixer", "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.11.1" + "issues": "https://github.com/nextcloud/coding-standard/issues", + "source": "https://github.com/nextcloud/coding-standard/tree/v1.1.1" }, - "time": "2020-10-26T10:28:16+00:00" + "time": "2023-06-01T12:05:01+00:00" }, { - "name": "doctrine/lexer", - "version": "1.2.1", + "name": "nextcloud/ocp", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "edb683cb75f1e4fd95577ed0b92109f532c781d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/edb683cb75f1e4fd95577ed0b92109f532c781d7", + "reference": "edb683cb75f1e4fd95577ed0b92109f532c781d7", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^8.2" + "php": "~8.0 || ~8.1 || ~8.2", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.1.4" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "dev-master": "28.0.0-dev" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "AGPL-3.0-or-later" ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" } ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], + "description": "Composer package containing Nextcloud's public API (classes, interfaces)", "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.1" + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2020-05-25T17:44:05+00:00" + "time": "2023-06-01T00:49:51+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v2.18.2", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "18f8c9d184ba777380794a389fabc179896ba913" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/18f8c9d184ba777380794a389fabc179896ba913", - "reference": "18f8c9d184ba777380794a389fabc179896ba913", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.2", - "doctrine/annotations": "^1.2", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", - "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0", - "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0 || ^5.0", - "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.4", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4.2", - "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", - "symfony/phpunit-bridge": "^5.2.1", - "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters.", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/Test/IsIdenticalConstraint.php", - "tests/TestCase.php" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "A tool to automatically fix PHP code style", + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.18.2" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2021-01-26T00:22:21+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { - "name": "nextcloud/coding-standard", - "version": "v0.4.0", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/nextcloud/coding-standard.git", - "reference": "57654010946567d063d231ff0e1ea44e1289f965" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/57654010946567d063d231ff0e1ea44e1289f965", - "reference": "57654010946567d063d231ff0e1ea44e1289f965", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^2.17", - "php": "^7.3|^8.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "Nextcloud\\CodingStandard\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Nextcloud coding standards for the php cs fixer", + "description": "Library for handling version information and constraints", "support": { - "issues": "https://github.com/nextcloud/coding-standard/issues", - "source": "https://github.com/nextcloud/coding-standard/tree/v0.4.0" + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "time": "2020-12-14T07:22:40+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "php-cs-fixer/diff", - "version": "v1.3.1", + "name": "php-cs-fixer/shim", + "version": "v3.17.0", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "f51b4aed90565c447136f1d015798f6f7c82490f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/f51b4aed90565c447136f1d015798f6f7c82490f", + "reference": "f51b4aed90565c447136f1d015798f6f7c82490f", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0 || ^8.0" + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" + "replace": { + "friendsofphp/php-cs-fixer": "self.version" }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." }, + "bin": [ + "php-cs-fixer", + "php-cs-fixer.phar" + ], + "type": "application", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "SpacePossum" + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], - "description": "sebastian/diff v2 backport support for PHP5.6", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], + "description": "A tool to automatically fix PHP code style", "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + "issues": "https://github.com/PHP-CS-Fixer/shim/issues", + "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.17.0" }, - "time": "2020-10-14T08:39:05+00:00" + "time": "2023-05-22T20:00:38+00:00" }, { "name": "php-parallel-lint/php-parallel-lint", - "version": "v1.2.0", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", - "reference": "474f18bc6cc6aca61ca40bfab55139de614e51ca" + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/474f18bc6cc6aca61ca40bfab55139de614e51ca", - "reference": "474f18bc6cc6aca61ca40bfab55139de614e51ca", + "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=5.4.0" + "php": ">=5.3.0" }, "replace": { "grogy/php-parallel-lint": "*", @@ -570,8 +409,8 @@ }, "require-dev": { "nette/tester": "^1.3 || ^2.0", - "php-parallel-lint/php-console-highlighter": "~0.3", - "squizlabs/php_codesniffer": "~3.0" + "php-parallel-lint/php-console-highlighter": "0.* || ^1.0", + "squizlabs/php_codesniffer": "^3.6" }, "suggest": { "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet" @@ -582,7 +421,7 @@ "type": "library", "autoload": { "classmap": [ - "./" + "./src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -599,124 +438,460 @@ "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", "support": { "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", - "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/master" + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.2" }, - "time": "2020-04-04T12:18:32+00:00" + "time": "2022-02-21T12:50:22+00:00" }, { - "name": "psalm/phar", - "version": "4.5.2", + "name": "phpunit/php-code-coverage", + "version": "7.0.15", "source": { "type": "git", - "url": "https://github.com/psalm/phar.git", - "reference": "ef4bd044508a1d44949c234ebc22b9719a0b399c" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "819f92bba8b001d4363065928088de22f25a3a48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/phar/zipball/ef4bd044508a1d44949c234ebc22b9719a0b399c", - "reference": "ef4bd044508a1d44949c234ebc22b9719a0b399c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48", + "reference": "819f92bba8b001d4363065928088de22f25a3a48", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": ">=7.2", + "phpunit/php-file-iterator": "^2.0.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.1.3 || ^4.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^4.2.2", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1.3" }, - "conflict": { - "vimeo/psalm": "*" + "require-dev": { + "phpunit/phpunit": "^8.2.2" + }, + "suggest": { + "ext-xdebug": "^2.7.2" }, - "bin": [ - "psalm.phar" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" ], - "description": "Composer-based Psalm Phar", "support": { - "issues": "https://github.com/psalm/phar/issues", - "source": "https://github.com/psalm/phar/tree/refs/tags/4.5.2" + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.15" }, - "time": "2021-02-13T22:04:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-07-26T12:20:09+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "phpunit/php-file-iterator", + "version": "2.0.5", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", + "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "filesystem", + "iterator" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/master" + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.5" }, - "time": "2017-02-14T16:28:37+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:42:26+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "phpunit/php-text-template", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:20:02+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "abandoned": true, + "time": "2020-08-04T08:28:15+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "8.5.33", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", + "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.0", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.2", + "phpunit/php-code-coverage": "^7.0.12", + "phpunit/php-file-iterator": "^2.0.4", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.5", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.3", + "sebastian/exporter": "^3.1.5", + "sebastian/global-state": "^3.0.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", + "sebastian/version": "^2.0.1" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.33" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } + ], + "time": "2023-02-27T13:04:50+00:00" + }, + { + "name": "psalm/phar", + "version": "4.30.0", + "source": { + "type": "git", + "url": "https://github.com/psalm/phar.git", + "reference": "33723713902e1345904a5c9064ef7848bee0d490" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/phar/zipball/33723713902e1345904a5c9064ef7848bee0d490", + "reference": "33723713902e1345904a5c9064ef7848bee0d490", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "vimeo/psalm": "*" + }, + "bin": [ + "psalm.phar" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer-based Psalm Phar", + "support": { + "issues": "https://github.com/psalm/phar/issues", + "source": "https://github.com/psalm/phar/tree/4.30.0" + }, + "time": "2022-11-06T20:41:58+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "Psr\\Clock\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -726,47 +901,50 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Standard interfaces for event handling.", + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", "keywords": [ - "events", + "clock", + "now", "psr", - "psr-14" + "psr-20", + "time" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" }, - "time": "2019-01-08T18:20:26+00:00" + "time": "2022-11-25T14:36:26+00:00" }, { - "name": "psr/log", - "version": "1.1.3", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -776,295 +954,676 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "log", - "psr", - "psr-3" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { - "name": "roave/security-advisories", - "version": "dev-master", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "5f40d4d577a71466f9723122251b46bdaf634709" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5f40d4d577a71466f9723122251b46bdaf634709", - "reference": "5f40d4d577a71466f9723122251b46bdaf634709", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "4dac38892bfbf1fc7536b70b0a1f60718b39af1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/4dac38892bfbf1fc7536b70b0a1f60718b39af1c", + "reference": "4dac38892bfbf1fc7536b70b0a1f60718b39af1c", + "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", - "adodb/adodb-php": "<5.20.12", + "admidio/admidio": "<4.1.9", + "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", + "aheinze/cockpit": "<=2.2.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<1.5", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", "amphp/http": "<1.0.1", "amphp/http-client": ">=4,<4.4", - "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<=1.0.1|>=2,<=2.2.4", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6|>=2.6,<2.7.10|>=3,<3.0.12|>=3.1,<3.1.3", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "automad/automad": "<1.8", + "awesome-support/awesome-support": "<=6.0.7", "aws/aws-sdk-php": ">=3,<3.2.1", + "azuracast/azuracast": "<0.18.3", + "backdrop/backdrop": "<1.24.2", + "badaso/core": "<2.7", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", - "baserproject/basercms": ">=4,<=4.3.6|>=4.4,<4.4.1", - "bolt/bolt": "<3.7.1", + "barryvdh/laravel-translation-manager": "<0.6.2", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<4.7.5", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bigfork/silverstripe-form-capture": ">=3,<=3.1", + "billz/raspap-webgui": "<=2.6.6", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "bottelet/flarepoint": "<2.2.1", "brightlocal/phpwhois": "<=4.2.5", - "buddypress/buddypress": "<5.1.2", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", - "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|= 1.3.7|>=4.1,<4.1.4", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", - "centreon/centreon": "<18.10.8|>=19,<19.4.5", + "catfan/medoo": "<1.7.5", + "centreon/centreon": "<22.10-beta.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "cockpit-hq/cockpit": "<2.4.1", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", - "composer/composer": "<=1-alpha.11", + "codeigniter4/framework": "<4.3.5", + "codeigniter4/shield": "<1-beta.4|= 1.0.0-beta", + "codiad/codiad": "<=2.8.4", + "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", + "concrete5/concrete5": "<9.2|>= 9.0.0RC1, < 9.1.3", + "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": ">=4,<4.4.52|>=4.5,<4.9.6|= 4.10.0", + "contao/core-bundle": "<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "craftcms/cms": ">= 4.0.0-RC1, <= 4.4.5|>= 4.0.0-RC1, <= 4.4.6|<=3.8.5|>=4,<4.4.6|>= 4.0.0-RC1, < 4.4.6|>= 4.0.0-RC1, < 4.3.7|>= 4.0.0-RC1, < 4.2.1", + "croogo/croogo": "<3.0.7", + "cuyz/valinor": "<0.12", + "czproject/git-php": "<4.0.3", + "darylldoyle/safe-svg": "<1.9.10", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", "doctrine/doctrine-bundle": "<1.5.2", "doctrine/doctrine-module": "<=0.7.1", "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", - "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", - "dolibarr/dolibarr": "<11.0.4", - "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.74|>=8,<8.8.11|>=8.9,<8.9.9|>=9,<9.0.8", - "drupal/drupal": ">=7,<7.74|>=8,<8.8.11|>=8.9,<8.9.9|>=9,<9.0.8", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<17.0.1|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.2|= 2.0.2", + "drupal/core": ">=7,<7.96|>=8,<9.4.14|>=9.5,<9.5.8|>=10,<10.0.8", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "dweeves/magmi": "<=0.7.24", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "elefant/cms": "<1.3.13", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "encore/laravel-admin": "<=1.8.19", "endroid/qr-code-bundle": "<3.4.2", - "enshrined/svg-sanitize": "<0.13.1", + "enshrined/svg-sanitize": "<0.15", "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "= 3.0.0|<2.2.3", "ezsystems/demobundle": ">=5.4,<5.4.6.1", "ezsystems/ez-support-tools": ">=2.2,<2.2.3", "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", - "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": ">=1,<1.0.2.1", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<1.2.5.1|>=1.3,<1.3.26", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.7.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.2|>=6,<6.7.9.1|>=6.8,<6.13.6.3|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.7.1", - "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.2|>=2011,<2017.12.7.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.5.1", + "ezsystems/ezpublish-kernel": "<6.13.8.2|>=7,<7.5.30", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", - "ezsystems/repository-forms": ">=2.3,<2.3.2.1", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<4.1.1", - "firebase/php-jwt": "<2", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.8", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filegator/filegator": "<7.8", + "firebase/php-jwt": "<6", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.7", + "flarum/mentions": "<1.6.3", "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3-beta.2,<1.1.7", + "fof/upload": "<1.2.3", "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<11", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "froala/wysiwyg-editor": "<3.2.7", + "froxlor/froxlor": "<2.0.16", "fuel/core": "<1.8.1", - "getgrav/grav": "<1.7-beta.8", - "getkirby/cms": ">=3,<3.4.5", + "funadmin/funadmin": "<=3.2", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "getgrav/grav": "<1.7.34", + "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1", "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "google/protobuf": "<3.15", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", - "gree/jose": "<=2.2", + "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", - "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1", + "grumpydictator/firefly-iii": "<6", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "= 2.31|<=2.31", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/post-install": "<=1.0.4", + "ibexa/user": ">=4,<4.4.3", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", - "illuminate/database": "<6.20.14|>=7,<7.30.4|>=8,<8.24", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", - "illuminate/view": ">=7,<7.1.2", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "impresscms/impresscms": "<=1.4.3", + "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<=4.2.1", + "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", - "james-heinrich/getid3": "<1.9.9", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", + "jasig/phpcas": "<1.3.3", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<1.4.4|>=2,<2.0.1", + "joomla/input": ">=2,<2.0.2", "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "kimai/kimai": "<1.1", "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<1.4.2", + "krayin/laravel-crm": "<1.2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laravel/framework": "<6.20.14|>=7,<7.30.4|>=8,<8.24", + "laminas/laminas-diactoros": "<2.18.1|>=2.24,<2.24.2|>=2.25,<2.25.2|= 2.23.0|= 2.22.0|= 2.21.0|= 2.20.0|= 2.19.0", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=9", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", - "librenms/librenms": "<1.53", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<22.10", + "liftkit/database": "<2.13.2", + "limesurvey/limesurvey": "<3.27.19", + "livehelperchat/livehelperchat": "<=3.91", "livewire/livewire": ">2.2.4,<2.2.6", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "luyadev/yii-helpers": "<1.2.1", "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", "magento/magento1ce": "<1.9.4.3", "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "maikuolan/phpmussel": ">=1,<1.6", + "mantisbt/mantisbt": "<=2.25.5", "marcwillmann/turn": "<0.3.3", - "mautic/core": "<2.16.5|>=3,<3.2.4|= 2.13.1", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<4.3|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "mediawiki/matomo": "<2.4.3", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.0.1", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microweber/microweber": "<1.3.4", + "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", + "modx/revolution": "<= 2.8.3-pl|<2.8", + "mojo42/jirafeau": "<4.4", "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.2-rc.2|= 3.11", + "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.4", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nystudio107/craft-seomatic": "<3.3", + "nilsteampassnet/teampass": "<3.0.9", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "nukeviet/nukeviet": "<4.5.2", + "nyholm/psr7": "<1.6.1", + "nystudio107/craft-seomatic": "<3.4.12", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", - "october/backend": ">=1.0.319,<1.0.470", - "october/cms": "= 1.0.469|>=1.0.319,<1.0.469", - "october/october": ">=1.0.319,<1.0.466", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.0.66", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.7.4", + "opencart/opencart": "<=3.0.3.7", "openid/php-openid": "<2.3", - "openmage/magento-lts": "<19.4.8|>=20,<20.0.4", + "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", "orchid/platform": ">=9,<9.4.4", - "oro/crm": ">=1.7,<1.7.4", - "oro/platform": ">=1.7,<1.7.4", + "oro/commerce": ">=4.1,<5.0.6", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", + "packbackbooks/lti-1-3-php-library": "<5", "padraic/humbug_get_contents": "<1.1.2", "pagarme/pagarme-php": ">=0,<3", + "pagekit/pagekit": "<=1.0.18", "paragonie/random_compat": "<2", "passbolt/passbolt_api": "<2.11", "paypal/merchant-sdk-php": "<3.12", - "pear/archive_tar": "<1.4.12", + "pear/archive_tar": "<1.4.14", + "pear/crypt_gpg": "<1.6.7", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", - "phpfastcache/phpfastcache": ">=5,<5.0.13", - "phpmailer/phpmailer": "<6.1.6", + "phanan/koel": "<5.1.4", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": ">=3.2,<3.2.10|>=3.3,<3.3.1", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<4.9.6|>=5,<5.0.3", - "phpoffice/phpexcel": "<1.8.2", + "phpmyadmin/phpmyadmin": "<5.2.1", + "phpmyfaq/phpmyfaq": "<=3.1.7", + "phpoffice/phpexcel": "<1.8", "phpoffice/phpspreadsheet": "<1.16", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.19", + "phpservermon/phpservermon": "<=3.5.2", + "phpsysinfo/phpsysinfo": "<3.2.5", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", - "pimcore/pimcore": "<6.3", - "pocketmine/pocketmine-mp": "<3.15.4", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pimcore/customer-management-framework-bundle": "<3.3.10", + "pimcore/data-hub": "<1.2.4", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<10.5.21", + "pixelfed/pixelfed": "<=0.11.4", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "< 4.18.0-ALPHA2|<4.12.5|>= 4.0.0-BETA5, < 4.4.2", + "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", - "prestashop/contactform": ">1.0.1,<4.3", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/productcomments": ">=4,<4.2.1", + "prestashop/prestashop": "<8.0.4", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", - "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<0.7.19|>=1-rc.0,<=1-rc.6", + "pterodactyl/panel": "<1.7", + "ptrofimov/beanstalk_console": "<1.7.14", "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6-beta", + "pyrocms/pyrocms": "<=3.9.1", "rainlab/debugbar-plugin": "<3.1", + "rankmath/seo-by-rank-math": "<=1.0.95", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", + "remdex/livehelperchat": "<3.99", + "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", + "roots/soil": "<4.1", + "rudloff/alltube": "<3.0.3", + "s-cart/core": "<6.9", + "s-cart/s-cart": "<6.9", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.3.4", - "shopware/platform": "<=6.3.5", - "shopware/shopware": "<5.6.9", - "silverstripe/admin": ">=1.0.3,<1.0.4|>=1.1,<1.1.1", - "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", - "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "shopware/core": "<=6.4.20", + "shopware/platform": "<=6.4.20", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.14", + "shopware/storefront": "<=6.4.8.1", + "shopxo/shopxo": "<2.2.6", + "showdoc/showdoc": "<2.10.4", + "silverstripe/admin": "<1.12.7", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.4.7|>=4.5,<4.5.4", - "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.1.2|>=3.2,<3.2.4", + "silverstripe/framework": "<4.12.5", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|>=4.1.1,<4.1.2|>=4.2.2,<4.2.3|= 4.0.0-alpha1", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", - "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", "silverstripe/userforms": "<3", + "silverstripe/versioned-admin": ">=1,<1.11.1", "simple-updates/phpwhois": "<=1", "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", "simplesamlphp/simplesamlphp": "<1.18.6", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.33", + "smarty/smarty": "<3.1.48|>=4,<4.3.1", + "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", + "spatie/browsershot": "<3.57.4", + "spipu/html2pdf": "<5.2.4", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<0.29.2", + "ssddanbrown/bookstack": "<22.2.3", + "statamic/cms": "<3.2.39|>=3.3,<3.3.2", "stormpath/sdk": ">=0,<9.9.99", - "studio-42/elfinder": "<2.1.49", - "sulu/sulu": "<1.6.34|>=2,<2.0.10|>=2.1,<2.1.1", + "studio-42/elfinder": "<2.1.59", + "subrion/cms": "<=4.2.1", + "sukohi/surpass": "<1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "sumocoders/framework-user-bundle": "<1.4", + "swag/paypal": "<5.4.4", "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", - "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3", + "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", "symfony/mime": ">=4.3,<4.3.8", "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/polyfill": ">=1,<1.10", "symfony/polyfill-php55": ">=1,<1.10", "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", - "symfony/security": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.37|>=3,<3.3.17|>=3.4,<3.4.7|>=4,<4.0.7", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-guard": ">=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", - "symfony/serializer": ">=2,<2.0.11", - "symfony/symfony": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", + "tastyigniter/tastyigniter": "<3.3", + "tcg/voyager": "<=1.4", "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<=5.1.7", + "thorsten/phpmyfaq": "<3.2-beta", + "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", + "tinymighty/wiki-seo": "<1.2.2", "titon/framework": ">=0,<9.9.99", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<6.0.14", + "topthink/think": "<=6.1.1", + "topthink/thinkphp": "<=3.2.3", + "tribalsystems/zenario": "<=9.3.57595", "truckersmp/phpwhois": "<=4.3.1", - "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.23|>=10,<10.4.10", - "typo3/cms-core": ">=8,<8.7.38|>=9,<9.5.23|>=10,<10.4.10", - "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", - "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", + "ttskch/pagination-service-provider": "<1", + "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", + "typo3/cms": "<2.0.5|>=3,<3.0.3|>=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": "<8.7.51|>=9,<9.5.40|>=10,<10.4.36|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<1.5|>=2,<2.1.1", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", + "unisharp/laravel-filemanager": "<=2.5.1", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", + "vanilla/safecurl": "<0.9.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<4.8.1", "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.5.4", + "wanglelecc/laracms": "<=1.0.3", + "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webpa/webpa": "<3.1.2", + "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", + "woocommerce/woocommerce": "<6.6", + "wp-cli/wp-cli": "<2.5", + "wp-graphql/wp-graphql": "<0.3.5", + "wpanel/wpanel4-cms": "<=4.3.1", + "wpcloud/wp-stateless": "<3.2", + "wwbn/avideo": "<=12.4", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yeswiki/yeswiki": "<4.1", + "yetiforce/yetiforce-crm": "<=6.4", + "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", - "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii": "<1.1.27", "yiisoft/yii2": "<2.0.38", "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<2.0.15", + "yiisoft/yii2-dev": "<2.0.43", "yiisoft/yii2-elasticsearch": "<2.0.5", - "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-gii": "<=2.2.4", "yiisoft/yii2-jui": "<2.0.4", "yiisoft/yii2-redis": "<2.0.8", - "yourls/yourls": "<1.7.4", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "zendesk/zendesk_api_client_php": "<2.2.11", "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", - "zendframework/zend-diactoros": ">=1,<1.8.4", - "zendframework/zend-feed": ">=1,<2.10.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-http": ">=1,<2.8.1", + "zendframework/zend-http": "<2.8.1", "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", @@ -1073,14 +1632,15 @@ "zendframework/zend-validator": ">=2.3,<2.3.6", "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": "<2.5.1", + "zendframework/zendframework": "<=3", "zendframework/zendframework1": "<1.12.20", "zendframework/zendopenid": ">=2,<2.0.2", "zendframework/zendxml": ">=1,<1.0.1", "zetacomponents/mail": "<1.8.2", "zf-commons/zfc-user": "<1.2.2", "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", - "zfr/zfr-oauth2-server-module": "<0.1.2" + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" }, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", @@ -1100,6 +1660,9 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], "support": { "issues": "https://github.com/Roave/SecurityAdvisories/issues", "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" @@ -1114,564 +1677,793 @@ "type": "tidelift" } ], - "time": "2021-02-10T03:02:31+00:00" + "time": "2023-06-01T20:04:19+00:00" }, { - "name": "symfony/console", - "version": "v5.2.3", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/89d4b176d12a2946a1ae4e34906a025b7b6b135a", - "reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/polyfill-php80": "^1.15", - "symfony/service-contracts": "^1.1|^2", - "symfony/string": "^5.1" + "php": ">=5.6" }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "require-dev": { + "phpunit/phpunit": "^8.5" }, - "provide": { - "psr/log-implementation": "1.0" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" + "autoload": { + "classmap": [ + "src/" + ] }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ - "cli", - "command line", - "console", - "terminal" + "comparator", + "compare", + "equality" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.3" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:31:48+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6296a0c086dd0117c1b78b059374d7fcbe7545ae", + "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "url": "https://github.com/fabpot", + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", "type": "github" + } + ], + "time": "2023-05-07T05:30:20+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:53:42+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/73a9676f2833b9a7c36968f9d882589cd75511e6", + "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "time": "2021-01-28T22:06:19+00:00" + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:00:17+00:00" }, { - "name": "symfony/deprecation-contracts", - "version": "v2.2.0", + "name": "sebastian/global-state", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/de036ec91d55d2a9e0db2ba975b512cdb1c23921", + "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-10T06:55:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-master": "3.0.x-dev" } }, "autoload": { - "files": [ - "function.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/master" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2020-11-30T07:40:27+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v5.2.3", + "name": "sebastian/object-reflector", + "version": "1.1.2", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4f9760f8074978ad82e2ce854dff79a71fe45367" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4f9760f8074978ad82e2ce854dff79a71fe45367", - "reference": "4f9760f8074978ad82e2ce854dff79a71fe45367", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/event-dispatcher-contracts": "^2", - "symfony/polyfill-php80": "^1.15" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "php": ">=7.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/error-handler": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^4.4|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "phpunit/phpunit": "^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.3" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-27T10:36:42+00:00" + "time": "2020-11-30T07:37:18+00:00" }, { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.2.0", + "name": "sebastian/recursion-context", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "0ba7d54483095a198fa51781bc608d17e84dffa2" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ba7d54483095a198fa51781bc608d17e84dffa2", - "reference": "0ba7d54483095a198fa51781bc608d17e84dffa2", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" + "php": ">=7.0" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" + "require-dev": { + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-master": "3.0.x-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.2.0" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2020-11-30T07:34:24+00:00" }, { - "name": "symfony/filesystem", - "version": "v5.2.3", + "name": "sebastian/resource-operations", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "262d033b57c73e8b59cd6e68a45c528318b15038" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/262d033b57c73e8b59cd6e68a45c528318b15038", - "reference": "262d033b57c73e8b59cd6e68a45c528318b15038", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.3" + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-27T10:01:46+00:00" + "time": "2020-11-30T07:30:19+00:00" }, { - "name": "symfony/finder", - "version": "v5.2.3", + "name": "sebastian/type", + "version": "1.1.4", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "4adc8d172d602008c204c2e16956f99257248e03" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4adc8d172d602008c204c2e16956f99257248e03", - "reference": "4adc8d172d602008c204c2e16956f99257248e03", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.3" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-28T22:06:19+00:00" + "time": "2020-11-30T07:25:11+00:00" }, { - "name": "symfony/options-resolver", - "version": "v5.2.3", + "name": "sebastian/version", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.15" + "php": ">=5.6" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.2.3" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-01-27T12:56:27+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.22.0", + "name": "symfony/console", + "version": "v5.4.19", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "url": "https://github.com/symfony/console.git", + "reference": "dccb8d251a9017d5994c988b034d3e18aaabf740" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/symfony/console/zipball/dccb8d251a9017d5994c988b034d3e18aaabf740", + "reference": "dccb8d251a9017d5994c988b034d3e18aaabf740", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { - "ext-ctype": "For best performance" + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" + "Symfony\\Component\\Console\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1680,24 +2472,24 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "cli", + "command line", + "console", + "terminal" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0" + "source": "https://github.com/symfony/console/tree/v5.4.19" }, "funding": [ { @@ -1713,44 +2505,38 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2023-01-01T08:32:19+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.22.0", + "name": "symfony/deprecation-contracts", + "version": "v3.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "267a9adeb8ecb8071040a740930e077cdfb987af" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/267a9adeb8ecb8071040a740930e077cdfb987af", - "reference": "267a9adeb8ecb8071040a740930e077cdfb987af", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" + "php": ">=8.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "3.0-dev" }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - }, "files": [ - "bootstrap.php" + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1767,18 +2553,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's grapheme_* functions", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -1794,32 +2572,35 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.22.0", + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "6e971c891537eb617a00bb07a43d182a6915faba" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/6e971c891537eb617a00bb07a43d182a6915faba", - "reference": "6e971c891537eb617a00bb07a43d182a6915faba", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-ctype": "*" + }, "suggest": { - "ext-intl": "For best performance" + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1827,15 +2608,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "files": [ "bootstrap.php" ], - "classmap": [ - "Resources/stubs" - ] + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1843,26 +2621,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "intl", - "normalizer", + "ctype", "polyfill", - "portable", - "shim" + "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" }, "funding": [ { @@ -1878,32 +2654,32 @@ "type": "tidelift" } ], - "time": "2021-01-07T17:09:11+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.22.0", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { - "ext-mbstring": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1911,12 +2687,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1932,17 +2708,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "grapheme", + "intl", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" }, "funding": [ { @@ -1958,35 +2735,49 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", "shasum": "" }, "require": { "php": ">=7.1" }, - "type": "metapackage", + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2001,16 +2792,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "intl", + "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" }, "funding": [ { @@ -2026,29 +2819,35 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.22.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2056,12 +2855,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2077,16 +2876,17 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" }, "funding": [ { @@ -2102,20 +2902,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", "shasum": "" }, "require": { @@ -2124,7 +2924,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2132,12 +2932,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -2165,7 +2965,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" }, "funding": [ { @@ -2181,20 +2981,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.22.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { @@ -2203,7 +3003,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2211,12 +3011,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -2248,69 +3048,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-01-07T16:49:33+00:00" - }, - { - "name": "symfony/process", - "version": "v5.2.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f", - "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.15" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.2.3" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, "funding": [ { @@ -2326,25 +3064,28 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.0" + "php": ">=8.0.2", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { "symfony/service-implementation": "" @@ -2352,7 +3093,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -2389,7 +3130,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" }, "funding": [ { @@ -2405,30 +3146,45 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2022-05-30T19:17:58+00:00" }, { - "name": "symfony/stopwatch", - "version": "v5.2.3", + "name": "symfony/string", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "b12274acfab9d9850c52583d136a24398cdf1a0c" + "url": "https://github.com/symfony/string.git", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b12274acfab9d9850c52583d136a24398cdf1a0c", - "reference": "b12274acfab9d9850c52583d136a24398cdf1a0c", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1.0|^2" + "php": ">=8.0.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" + "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -2440,18 +3196,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a way to profile code", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.2.3" + "source": "https://github.com/symfony/string/tree/v6.0.19" }, "funding": [ { @@ -2467,101 +3231,68 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { - "name": "symfony/string", - "version": "v5.2.3", + "name": "theseer/tokenizer", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "c95468897f408dd0aca2ff582074423dd0455122" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/c95468897f408dd0aca2ff582074423dd0455122", - "reference": "c95468897f408dd0aca2ff582074423dd0455122", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "files": [ - "Resources/functions.php" - ], - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { - "source": "https://github.com/symfony/string/tree/v5.2.3" + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/theseer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2021-01-25T15:14:59+00:00" + "time": "2021-07-28T10:34:58+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": { "roave/security-advisories": 20, - "christophwurst/nextcloud": 20 + "nextcloud/ocp": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.3.0" } diff --git a/krankerl.toml b/krankerl.toml index 4c83a069..e56a540e 100644 --- a/krankerl.toml +++ b/krankerl.toml @@ -1,10 +1,13 @@ [package] before_cmds = [ + "mkdir -p bin/x86_64 bin/armv7 bin/aarch64", + "cargo clean", "cross build --release --target=armv7-unknown-linux-musleabihf", + "cp target/armv7-unknown-linux-musleabihf/release/notify_push bin/armv7", + "cargo clean", "cross build --release --target=aarch64-unknown-linux-musl", + "cp target/aarch64-unknown-linux-musl/release/notify_push bin/aarch64", + "cargo clean", "cargo build --release --target=x86_64-unknown-linux-musl", - "mkdir -p bin/x86_64 bin/armv7 bin/aarch64", "cp target/x86_64-unknown-linux-musl/release/notify_push bin/x86_64", - "cp target/armv7-unknown-linux-musleabihf/release/notify_push bin/armv7", - "cp target/aarch64-unknown-linux-musl/release/notify_push bin/aarch64", ] diff --git a/lib/BinaryFinder.php b/lib/BinaryFinder.php new file mode 100644 index 00000000..0c35637f --- /dev/null +++ b/lib/BinaryFinder.php @@ -0,0 +1,43 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\NotifyPush; + +class BinaryFinder { + public function getArch(): string { + $arch = php_uname('m'); + if (strpos($arch, 'armv7') === 0) { + return 'armv7'; + } + if (strpos($arch, 'aarch64') === 0) { + return 'aarch64'; + } + return $arch; + } + + public function getBinaryPath(): string { + $basePath = realpath(__DIR__ . '/../bin/'); + $arch = $this->getArch(); + return "$basePath/$arch/notify_push"; + } +} diff --git a/lib/CSPListener.php b/lib/CSPListener.php index 37219893..d6b57c01 100644 --- a/lib/CSPListener.php +++ b/lib/CSPListener.php @@ -30,6 +30,9 @@ use OCP\Security\CSP\AddContentSecurityPolicyEvent; use Psr\Log\LoggerInterface; +/** + * @implements IEventListener + */ class CSPListener implements IEventListener { private $config; private $logger; diff --git a/lib/Command/Metrics.php b/lib/Command/Metrics.php index 7589dea2..3eeb0bea 100644 --- a/lib/Command/Metrics.php +++ b/lib/Command/Metrics.php @@ -70,7 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln("Total connection count: " . $metrics['total_connection_count']); $output->writeln("Total database query count: " . $metrics['mapping_query_count']); $output->writeln("Events received: " . $metrics['events_received']); - $output->writeln("Messages send: " . $metrics['messages_send']); + $output->writeln("Messages sent: " . $metrics['messages_sent']); return 0; } else { $output->writeln("No metrics received from push server"); diff --git a/lib/Command/Reset.php b/lib/Command/Reset.php new file mode 100644 index 00000000..b7f2911f --- /dev/null +++ b/lib/Command/Reset.php @@ -0,0 +1,55 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\NotifyPush\Command; + +use OCA\NotifyPush\Queue\IQueue; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Reset extends Command { + private $queue; + + public function __construct( + IQueue $queue + ) { + parent::__construct(); + $this->queue = $queue; + } + + /** + * @return void + */ + protected function configure() { + $this + ->setName('notify_push:reset') + ->setDescription('Cancel all active connections to the push server'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $this->queue->push("notify_signal", "reset"); + return 0; + } +} diff --git a/lib/Listener.php b/lib/Listener.php index 29f42919..8870dda2 100644 --- a/lib/Listener.php +++ b/lib/Listener.php @@ -23,11 +23,13 @@ namespace OCA\NotifyPush; +use OC\Files\Storage\Wrapper\Jail; use OCA\NotifyPush\Queue\IQueue; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; use OCP\EventDispatcher\Event; use OCP\Files\Cache\ICacheEvent; +use OCP\Files\IHomeStorage; use OCP\Group\Events\UserAddedEvent; use OCP\Group\Events\UserRemovedEvent; use OCP\Notification\IApp; @@ -38,7 +40,7 @@ use OCP\Share\IShare; class Listener implements IConsumer, IApp, INotifier, IDismissableNotifier { - private $queue; + private IQueue $queue; public function __construct(IQueue $queue) { $this->queue = $queue; @@ -46,9 +48,31 @@ public function __construct(IQueue $queue) { public function cacheListener(Event $event): void { if ($event instanceof ICacheEvent) { + // ignore files in home storage but outside home directory (trashbin, versions, etc) + if ( + $event->getStorage()->instanceOfStorage(IHomeStorage::class) && !( + $event->getPath() === 'files' || strpos($event->getPath(), "files/") === 0 + ) + ) { + return; + } + // ignore appdata + if (strpos($event->getPath(), 'appdata_') === 0) { + return; + } + $path = $event->getPath(); + + $storage = $event->getStorage(); + while ($storage->instanceOfStorage(Jail::class)) { + /** @var $storage Jail */ + $path = $storage->getUnjailedPath($path); + $storage = $storage->getUnjailedStorage(); + } + $this->queue->push('notify_storage_update', [ 'storage' => $event->getStorageId(), - 'path' => $event->getPath(), + 'path' => $path, + 'file_id' => $event->getFileId(), ]); } } diff --git a/lib/Migration/Install.php b/lib/Migration/Install.php index 2c94063f..e49b7301 100644 --- a/lib/Migration/Install.php +++ b/lib/Migration/Install.php @@ -23,22 +23,26 @@ namespace OCA\NotifyPush\Migration; -use OCA\NotifyPush\SetupWizard; +use OCA\NotifyPush\BinaryFinder; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class Install implements IRepairStep { - private $setupWizard; + private $binaryFinder; - public function __construct(SetupWizard $setupWizard) { - $this->setupWizard = $setupWizard; + public function __construct(BinaryFinder $setupWizard) { + $this->binaryFinder = $setupWizard; } public function getName() { return 'Set binary permissions'; } + /** + * @return void + */ public function run(IOutput $output) { - $this->setupWizard->testBinary(); + $path = $this->binaryFinder->getBinaryPath(); + @chmod($path, 0755); } } diff --git a/lib/Queue/IQueue.php b/lib/Queue/IQueue.php index ac14b517..8a0f35dc 100644 --- a/lib/Queue/IQueue.php +++ b/lib/Queue/IQueue.php @@ -24,5 +24,10 @@ namespace OCA\NotifyPush\Queue; interface IQueue { + /** + * @param string $channel + * @param mixed $message + * @return void + */ public function push(string $channel, $message); } diff --git a/lib/Queue/RedisQueue.php b/lib/Queue/RedisQueue.php index 52b73ff8..de9446e5 100644 --- a/lib/Queue/RedisQueue.php +++ b/lib/Queue/RedisQueue.php @@ -33,9 +33,6 @@ public function __construct($redis) { $this->redis = $redis; } - /** - * @return void - */ public function push(string $channel, $message) { $this->redis->publish($channel, json_encode($message)); } diff --git a/lib/SetupWizard.php b/lib/SetupWizard.php index 7c834b42..dce5b91b 100644 --- a/lib/SetupWizard.php +++ b/lib/SetupWizard.php @@ -25,48 +25,38 @@ use OCA\NotifyPush\Queue\IQueue; use OCA\NotifyPush\Queue\RedisQueue; -use OCP\App\IAppManager; use OCP\Http\Client\IClientService; use OCP\IConfig; use Symfony\Component\Console\Output\BufferedOutput; class SetupWizard { - private $appManager; private $queue; private $test; private $client; private $config; private $httpsCache = []; + private $binaryFinder; public function __construct( - IAppManager $appManager, IQueue $queue, SelfTest $test, IClientService $clientService, - IConfig $config + IConfig $config, + BinaryFinder $binaryFinder ) { - $this->appManager = $appManager; $this->queue = $queue; $this->test = $test; $this->client = $clientService->newClient(); $this->config = $config; + $this->binaryFinder = $binaryFinder; } public function getArch(): string { - $arch = php_uname('m'); - if (strpos($arch, 'armv7') === 0) { - return 'armv7'; - } - if (strpos($arch, 'aarch64') === 0) { - return 'aarch64'; - } - return $arch; + return $this->binaryFinder->getArch(); } private function getBinaryPath(): string { - $basePath = realpath(__DIR__ . '/../bin/'); - $arch = $this->getArch(); - return "$basePath/$arch/notify_push"; + return $this->binaryFinder->getBinaryPath(); } public function hasBundledBinaries(): bool { @@ -255,7 +245,7 @@ public function generateSystemdService(bool $selfSigned): string { [Service] Environment=PORT=7867 Environment=NEXTCLOUD_URL=$ncUrl -${selfSigned}ExecStart=$path $config +{$selfSigned}ExecStart=$path $config User=$user [Install] diff --git a/psalm.xml b/psalm.xml index ef985325..e7e00920 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ + + + - + diff --git a/src/config.rs b/src/config.rs index 7f0dadbf..07f2a57c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,8 @@ mod nc; use crate::config::nc::parse_config_file; -use color_eyre::eyre::ContextCompat; -use color_eyre::{eyre::WrapErr, Report, Result}; +use crate::error::ConfigError; +use crate::{Error, Result}; use derivative::Derivative; use redis::ConnectionInfo; use sqlx::any::AnyConnectOptions; @@ -12,9 +12,10 @@ use std::fmt::{Display, Formatter}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use structopt::StructOpt; +use structopt::{clap::AppSettings, StructOpt}; #[derive(StructOpt, Debug)] +#[structopt(global_setting = AppSettings::ColoredHelp)] #[structopt(name = "notify_push")] pub struct Opt { /// The database connect url @@ -68,6 +69,15 @@ pub struct Opt { /// Load other files named *.config.php in the config folder #[structopt(long)] pub glob_config: bool, + /// TLS certificate + #[structopt(long)] + pub tls_cert: Option, + /// TLS key + #[structopt(long)] + pub tls_key: Option, + /// The maximum debounce time between messages, in seconds. + #[structopt(long)] + pub max_debounce_time: Option, } #[derive(Debug)] @@ -81,6 +91,14 @@ pub struct Config { pub bind: Bind, pub allow_self_signed: bool, pub no_ansi: bool, + pub tls: Option, + pub max_debounce_time: usize, +} + +#[derive(Debug, Clone)] +pub struct TlsConfig { + pub key: PathBuf, + pub cert: PathBuf, } #[derive(Clone, Derivative)] @@ -107,18 +125,17 @@ impl Display for Bind { } impl TryFrom for Config { - type Error = Report; + type Error = Error; fn try_from(config: PartialConfig) -> Result { let socket_permissions = config .socket_permissions .map(|perm| { if perm.len() != 4 && !perm.starts_with('0') { - return Err(Report::msg( - "socket permissions should be provided in the octal form `0xxx`", - )); + return Err(ConfigError::SocketPermissions(perm, None)); } - Ok(u32::from_str_radix(&perm, 8)?) + Ok(u32::from_str_radix(&perm, 8) + .map_err(|e| ConfigError::SocketPermissions(perm, Some(e)))?) }) .transpose()? .unwrap_or(0o666); @@ -146,15 +163,13 @@ impl TryFrom for Config { let mut nextcloud_url = config .nextcloud_url - .ok_or_else(|| Report::msg("No nextcloud url configured"))?; + .ok_or_else(|| ConfigError::NoNextcloud)?; if !nextcloud_url.ends_with('/') { nextcloud_url.push('/'); } Ok(Config { - database: config - .database - .ok_or_else(|| Report::msg("No database url configured"))?, + database: config.database.ok_or_else(|| ConfigError::NoDatabase)?, database_prefix: config .database_prefix .unwrap_or_else(|| String::from("oc_")), @@ -165,6 +180,8 @@ impl TryFrom for Config { bind, allow_self_signed: config.allow_self_signed.unwrap_or(false), no_ansi: config.no_ansi.unwrap_or(false), + tls: config.tls, + max_debounce_time: config.max_debounce_time.unwrap_or(15), }) } } @@ -199,25 +216,36 @@ struct PartialConfig { pub socket_permissions: Option, pub allow_self_signed: Option, pub no_ansi: Option, + pub tls: Option, + pub max_debounce_time: Option, } impl PartialConfig { fn from_env() -> Result { - let database = parse_var("DATABASE_URL").wrap_err("Failed to parse DATABASE_URL")?; + let database = parse_var("DATABASE_URL")?; let database_prefix = var("DATABASE_PREFIX").ok(); - let redis = parse_var("REDIS_URL").wrap_err("Failed to parse REDIS_URL")?; + let redis = parse_var("REDIS_URL")?; let nextcloud_url = var("NEXTCLOUD_URL").ok(); - let port = parse_var("PORT").ok().wrap_err("Invalid PORT")?; - let metrics_port = parse_var("METRICS_PORT").wrap_err("Invalid METRICS_PORT")?; - let metrics_socket = - parse_var("METRICS_SOCKET_PATH").wrap_err("Invalid METRICS_SOCKET_PATH")?; + let port = parse_var("PORT")?; + let metrics_port = parse_var("METRICS_PORT")?; + let metrics_socket = parse_var("METRICS_SOCKET_PATH")?; let log_level = var("LOG").ok(); - let bind = parse_var("BIND").wrap_err("Invalid BIND")?; + let bind = parse_var("BIND")?; let socket = var("SOCKET_PATH").map(PathBuf::from).ok(); let socket_permissions = var("SOCKET_PERMISSIONS").ok(); let allow_self_signed = var("ALLOW_SELF_SIGNED").map(|val| val == "true").ok(); let no_ansi = var("NO_ANSI").map(|val| val == "true").ok(); + let tls_cert = parse_var("TLS_CERT")?; + let tls_key = parse_var("TLS_KEY")?; + + let tls = if let (Some(cert), Some(key)) = (tls_cert, tls_key) { + Some(TlsConfig { cert, key }) + } else { + None + }; + let max_debounce_time = parse_var("MAX_DEBOUNCE_TIME")?; + Ok(PartialConfig { database, database_prefix, @@ -232,14 +260,22 @@ impl PartialConfig { socket_permissions, allow_self_signed, no_ansi, + tls, + max_debounce_time, }) } fn from_file(file: impl AsRef, glob: bool) -> Result { - parse_config_file(file, glob) + Ok(parse_config_file(file, glob)?) } fn from_opt(opt: Opt) -> Self { + let tls = if let (Some(cert), Some(key)) = (opt.tls_cert, opt.tls_key) { + Some(TlsConfig { cert, key }) + } else { + None + }; + PartialConfig { database: opt.database_url, database_prefix: opt.database_prefix, @@ -258,6 +294,8 @@ impl PartialConfig { None }, no_ansi: if opt.no_ansi { Some(true) } else { None }, + tls, + max_debounce_time: opt.max_debounce_time, } } @@ -280,11 +318,13 @@ impl PartialConfig { socket_permissions: self.socket_permissions.or(fallback.socket_permissions), allow_self_signed: self.allow_self_signed.or(fallback.allow_self_signed), no_ansi: self.no_ansi.or(fallback.no_ansi), + tls: self.tls.or(fallback.tls), + max_debounce_time: self.max_debounce_time.or(fallback.max_debounce_time), } } } -fn parse_var(name: &str) -> Result> +fn parse_var(name: &'static str) -> Result> where T: FromStr + 'static, T::Err: std::error::Error + Sync + Send, @@ -293,5 +333,5 @@ where .ok() .map(|val| T::from_str(&val)) .transpose() - .map_err(Report::from) + .map_err(|e| ConfigError::Env(name, Box::new(e)).into()) } diff --git a/src/config/nc.rs b/src/config/nc.rs index 4a3d3424..17d26da4 100644 --- a/src/config/nc.rs +++ b/src/config/nc.rs @@ -1,11 +1,13 @@ use crate::config::PartialConfig; -use color_eyre::{eyre::WrapErr, Result}; +use crate::error::ConfigError; use nextcloud_config_parser::{parse, parse_glob}; use std::path::Path; -pub(super) fn parse_config_file(path: impl AsRef, glob: bool) -> Result { - let config = if glob { parse_glob(path) } else { parse(path) } - .wrap_err("Failed to parse nextcloud config")?; +pub(super) fn parse_config_file( + path: impl AsRef, + glob: bool, +) -> Result { + let config = if glob { parse_glob(path) } else { parse(path) }?; Ok(PartialConfig { database: Some(config.database.into()), diff --git a/src/connection.rs b/src/connection.rs index 89c000e4..1732db83 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,48 +1,69 @@ -use crate::message::{DebounceMap, MessageType}; +use crate::error::{AuthenticationError, WebSocketError}; +use crate::message::{PushMessage, SendQueue}; use crate::metrics::METRICS; +use crate::Result; use crate::{App, UserId}; use ahash::RandomState; -use color_eyre::{Report, Result}; use dashmap::DashMap; use futures::{future::select, pin_mut, SinkExt, StreamExt}; use std::net::IpAddr; use std::num::NonZeroUsize; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; -use tokio::sync::broadcast::{channel, Receiver, Sender}; +use tokio::sync::broadcast; use tokio::time::timeout; use warp::filters::ws::{Message, WebSocket}; const USER_CONNECTION_LIMIT: usize = 64; #[derive(Default)] -pub struct ActiveConnections(DashMap, RandomState>); +pub struct ActiveConnections(DashMap, RandomState>); impl ActiveConnections { - pub async fn add(&self, user: UserId) -> Result> { + pub async fn add(&self, user: UserId) -> Result> { if let Some(sender) = self.0.get(&user) { // stop a single user from trying to eat all the resources if sender.receiver_count() > USER_CONNECTION_LIMIT { - Err(Report::msg("connection limit exceeded")) + Err(AuthenticationError::LimitExceeded.into()) } else { Ok(sender.subscribe()) } } else { - let (tx, rx) = channel(4); + let (tx, rx) = broadcast::channel(4); self.0.insert(user, tx); Ok(rx) } } - pub async fn send_to_user(&self, user: &UserId, msg: MessageType) { + pub async fn send_to_user(&self, user: &UserId, msg: PushMessage) { if let Some(tx) = self.0.get(user) { tx.send(msg).ok(); } } } -pub async fn handle_user_socket(mut ws: WebSocket, app: Arc, forwarded_for: Vec) { +#[derive(Default)] +pub struct ConnectionOptions { + pub listen_file_id: AtomicBool, + pub max_debounce_time: usize, +} + +impl ConnectionOptions { + pub fn new(max_debounce_time: usize) -> Self { + ConnectionOptions { + max_debounce_time, + ..ConnectionOptions::default() + } + } +} + +pub async fn handle_user_socket( + mut ws: WebSocket, + app: Arc, + forwarded_for: Vec, + opts: ConnectionOptions, +) { let user_id = match timeout( Duration::from_secs(15), socket_auth(&mut ws, forwarded_for, &app), @@ -85,38 +106,66 @@ pub async fn handle_user_socket(mut ws: WebSocket, app: Arc, forwarded_for: let expect_pong = AtomicUsize::default(); let expect_pong = &expect_pong; - let transmit = async move { - let mut debounce = DebounceMap::default(); - loop { - match timeout(Duration::from_secs(30), rx.recv()).await { - Ok(Ok(msg)) => { - log::debug!(target: "notify_push::send", "Sending {} to {}", msg, user_id); - if debounce.should_send(&msg) { - METRICS.add_message(); - user_ws_tx.send(msg.into()).await.ok(); - } - } - Err(_timout) => { - let data = rand::random::().into(); - let last_ping = expect_pong.swap(data, Ordering::SeqCst); - if last_ping > 0 { - log::info!("{} didn't reply to ping, closing", user_id); - break; + let transmit = async { + let mut send_queue = SendQueue::default(); + + let mut reset = app.reset_rx(); + + let ping_interval = Duration::from_secs(30); + let mut last_send = Instant::now() - ping_interval; + + 'tx_loop: loop { + tokio::select! { + msg = timeout(Duration::from_millis(500), rx.recv()) => { + let now = Instant::now(); + match msg { + Ok(Ok(msg)) => { + if let Some(msg) = send_queue.push(msg, now) { + log::debug!(target: "notify_push::send", "Sending {} to {}", msg, user_id); + METRICS.add_message(); + last_send = now; + user_ws_tx.send(msg.into_message(&opts)).await.ok(); + } + } + Err(_timout) => { + for msg in send_queue.drain(now, METRICS.active_connection_count() + 50000, opts.max_debounce_time) { + last_send = now; + METRICS.add_message(); + log::debug!(target: "notify_push::send", "Sending debounced {} to {}", msg, user_id); + user_ws_tx.feed(msg.into_message(&opts)).await.ok(); + } + + if now.duration_since(last_send) > ping_interval { + let data = rand::random::().into(); + let last_ping = expect_pong.swap(data, Ordering::SeqCst); + if last_ping > 0 { + log::info!("{} didn't reply to ping, closing", user_id); + break; + } + log::debug!(target: "notify_push::send", "Sending ping to {}", user_id); + last_send = now; + user_ws_tx + .feed(Message::ping(data.to_le_bytes())) + .await + .ok(); + } + user_ws_tx.flush().await.ok(); + } + Ok(Err(_)) => { + // we dont care about dropped messages + } } - log::debug!(target: "notify_push::send", "Sending ping to {}", user_id); - user_ws_tx - .send(Message::ping(data.to_le_bytes())) - .await - .ok(); - } - Ok(Err(_)) => { - // we dont care about dropped messages - } - } + }, + _ = reset.recv() => { + user_ws_tx.close().await.ok(); + log::debug!("Connection closed by reset request"); + break 'tx_loop; + }, + }; } }; - let receive = async move { + let receive = async { // handle messages until the client closes the connection while let Some(result) = user_ws_rx.next().await { match result { @@ -127,6 +176,12 @@ pub async fn handle_user_socket(mut ws: WebSocket, app: Arc, forwarded_for: break; } } + Ok(msg) if msg.is_text() => { + let text = msg.to_str().unwrap_or_default(); + if text == "listen notify_file_id" { + opts.listen_file_id.store(true, Ordering::Relaxed); + } + } Ok(_) => {} Err(e) => { let formatted = e.to_string(); @@ -152,23 +207,27 @@ pub async fn handle_user_socket(mut ws: WebSocket, app: Arc, forwarded_for: METRICS.remove_connection(); } -async fn read_socket_auth_message(rx: &mut WebSocket) -> Result { +async fn read_socket_auth_message(rx: &mut WebSocket) -> Result { match rx.next().await { Some(Ok(msg)) => Ok(msg), - Some(Err(e)) => Err(Report::from(e).wrap_err("Socket error during authentication")), - None => Err(Report::msg("Client disconnected during authentication")), + Some(Err(e)) => Err(e.into()), + None => Err(WebSocketError::Disconnected), } } -async fn socket_auth(rx: &mut WebSocket, forwarded_for: Vec, app: &App) -> Result { +async fn socket_auth( + rx: &mut WebSocket, + forwarded_for: Vec, + app: &App, +) -> Result { let username_msg = read_socket_auth_message(rx).await?; let username = username_msg .to_str() - .map_err(|_| Report::msg("Invalid authentication message"))?; + .map_err(|_| AuthenticationError::InvalidMessage)?; let password_msg = read_socket_auth_message(rx).await?; let password = password_msg .to_str() - .map_err(|_| Report::msg("Invalid authentication message"))?; + .map_err(|_| AuthenticationError::InvalidMessage)?; // cleanup all pre_auth tokens older than 15s let cutoff = Instant::now() - Duration::from_secs(15); @@ -183,10 +242,11 @@ async fn socket_auth(rx: &mut WebSocket, forwarded_for: Vec, app: &App) } if !username.is_empty() { - app.nc_client + Ok(app + .nc_client .verify_credentials(username, password, forwarded_for) - .await + .await?) } else { - Err(Report::msg("Invalid credentials")) + Err(AuthenticationError::Invalid) } } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..eb46f56e --- /dev/null +++ b/src/error.rs @@ -0,0 +1,121 @@ +use flexi_logger::FlexiLoggerError; +use miette::Diagnostic; +use redis::RedisError; +use reqwest::StatusCode; +use std::net::AddrParseError; +use std::num::ParseIntError; +use thiserror::Error; + +#[derive(Debug, Error, Diagnostic)] +pub enum Error { + #[error(transparent)] + Database(#[from] DatabaseError), + #[error(transparent)] + Redis(#[from] RedisError), + #[error(transparent)] + #[diagnostic(transparent)] + Config(#[from] ConfigError), + #[error("Error while running self test: {0}")] + #[diagnostic(transparent)] + SelfTest(#[from] SelfTestError), + #[error("Failed to set signal hook")] + SignalHook(#[source] std::io::Error), + #[error("Failed to listen to socket")] + Socket(#[from] SocketError), + #[error("Error while handling authentication")] + Authentication(#[from] AuthenticationError), + #[error("Error while communicating with Nextcloud")] + NextCloud(#[from] NextCloudError), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum NextCloudError { + #[error(transparent)] + Request(#[from] reqwest::Error), + #[error("Invalid nextcloud url")] + NextcloudUrl(#[from] url::ParseError), + #[error("Error while connecting to nextcloud")] + NextcloudConnect(#[source] reqwest::Error), + #[error("Client error: {0}")] + Client(StatusCode), + #[error("Server error: {0}")] + Server(StatusCode), + #[error("Unexpected status code: {0}")] + Other(StatusCode), + #[error("{0} is not configured as a trusted domain for the nextcloud server")] + NotATrustedDomain(String), + #[error("Invalid response when getting test cookie")] + MalformedCookieResponse(#[source] ParseIntError), + #[error("Invalid response when testing if the push server is a trusted proxy")] + MalformedRemote(#[source] AddrParseError), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum DatabaseError { + #[error("Failed to connect to database")] + Connect(#[source] sqlx::Error), + #[error("Failed to query database")] + Query(#[source] sqlx::Error), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum SelfTestError { + #[error("Failed to test database access")] + Database(#[from] DatabaseError), + #[error("Failed to test redis access")] + Redis(#[from] RedisError), + #[error("Error while communicating with nextcloud instance")] + NextcloudCommunication(#[from] NextCloudError), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum SocketError { + #[error("Failed to bind to socket at {1}")] + Bind(#[source] std::io::Error, String), + #[error("Failed to set socket permissions")] + SocketPermissions(#[source] std::io::Error), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum ConfigError { + #[error("No redis server is configured")] + NoRedis, + #[error("No nextcloud server is configured")] + NoNextcloud, + #[error("No database server is configured")] + NoDatabase, + #[error("Error while parsing nextcloud config.php")] + #[diagnostic(transparent)] + Parse(#[from] nextcloud_config_parser::Error), + #[error("Invalid {0} environment variable")] + Env( + &'static str, + #[source] Box, + ), + #[error("socket permissions should be provided in the octal form `0xxx`, got {0}")] + SocketPermissions(String, Option), + #[error("Failed to parse log level")] + LogLevel(#[from] FlexiLoggerError), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum WebSocketError { + #[error("Client disconnected unexpectedly")] + Disconnected, + #[error(transparent)] + Error(#[from] warp::Error), +} + +#[derive(Debug, Error, Diagnostic)] +pub enum AuthenticationError { + #[error(transparent)] + Socket(#[from] WebSocketError), + #[error("Invalid authentication message")] + InvalidMessage, + #[error("Error while sending authentication request to nextcloud")] + Nextcloud(#[from] NextCloudError), + #[error("Invalid credentials")] + Invalid, + #[error("Connection limit exceeded for user")] + LimitExceeded, +} diff --git a/src/event.rs b/src/event.rs index f3a01f4b..ecb5662a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,6 +1,5 @@ use crate::metrics::METRICS; -use crate::{Redis, UserId}; -use color_eyre::{eyre::WrapErr, Result}; +use crate::{Redis, Result, UserId}; use parse_display::Display; use redis::Msg; use serde::Deserialize; @@ -13,6 +12,7 @@ use tokio_stream::{Stream, StreamExt}; pub struct StorageUpdate { pub storage: u32, pub path: String, + pub file_id: Option, } #[derive(Debug, Deserialize)] @@ -63,6 +63,12 @@ pub struct Custom { pub body: Value, } +#[derive(Debug, Deserialize, Display)] +#[serde(rename_all = "snake_case")] +pub enum Signal { + Reset, +} + #[derive(Debug, Display)] pub enum Event { #[display("storage update notification for storage {0.storage} and path {0.path}")] @@ -85,6 +91,8 @@ pub enum Event { Config(Config), #[display("{0} query")] Query(Query), + #[display("{0} signal")] + Signal(Signal), } #[derive(Debug, Error)] @@ -130,6 +138,9 @@ impl TryFrom for Event { "notify_query" => Ok(Event::Query(serde_json::from_slice( msg.get_payload_bytes(), )?)), + "notify_signal" => Ok(Event::Signal(serde_json::from_slice( + msg.get_payload_bytes(), + )?)), _ => Err(MessageDecodeError::UnsupportedEventType), } } @@ -138,10 +149,7 @@ impl TryFrom for Event { pub async fn subscribe( client: &Redis, ) -> Result>> { - let mut pubsub = client - .pubsub() - .await - .wrap_err("Failed to connect to redis")?; + let mut pubsub = client.pubsub().await?; let channels = [ "notify_storage_update", "notify_group_membership_update", @@ -153,12 +161,10 @@ pub async fn subscribe( "notify_custom", "notify_config", "notify_query", + "notify_signal", ]; for channel in channels.iter() { - pubsub - .subscribe(*channel) - .await - .wrap_err("Failed to subscribe to redis pubsub")?; + pubsub.subscribe(*channel).await?; } Ok(pubsub.into_on_message().map(|event| { diff --git a/src/lib.rs b/src/lib.rs index d7556049..0a08357a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,16 @@ -use crate::config::{Bind, Config}; -use crate::connection::{handle_user_socket, ActiveConnections}; +use crate::config::{Bind, Config, TlsConfig}; +use crate::connection::{handle_user_socket, ActiveConnections, ConnectionOptions}; +pub use crate::error::Error; +use crate::error::{SelfTestError, SocketError}; use crate::event::{ Activity, Custom, Event, GroupUpdate, Notification, PreAuth, ShareCreate, StorageUpdate, }; -use crate::message::MessageType; +use crate::message::{PushMessage, UpdatedFiles}; use crate::metrics::METRICS; use crate::redis::Redis; use crate::storage_mapping::StorageMapping; pub use crate::user::UserId; use ahash::RandomState; -use color_eyre::{eyre::WrapErr, Result}; use dashmap::DashMap; use flexi_logger::LoggerHandle; use futures::future::{select, Either}; @@ -25,8 +26,8 @@ use std::os::unix::fs::PermissionsExt; use std::sync::atomic::{AtomicU32, Ordering}; use std::time::{Duration, Instant}; use tokio::net::UnixListener; -use tokio::sync::oneshot; use tokio::sync::Mutex; +use tokio::sync::{broadcast, oneshot}; use tokio::time::sleep; use tokio_stream::wrappers::UnixListenerStream; use warp::filters::addr::remote; @@ -35,6 +36,7 @@ use warp_real_ip::get_forwarded_for; pub mod config; pub mod connection; +pub mod error; pub mod event; pub mod message; pub mod metrics; @@ -43,6 +45,8 @@ pub mod redis; pub mod storage_mapping; pub mod user; +pub type Result = std::result::Result; + pub struct App { connections: ActiveConnections, nc_client: nc::Client, @@ -51,6 +55,8 @@ pub struct App { test_cookie: AtomicU32, redis: Redis, log_handle: Mutex, + reset_tx: broadcast::Sender<()>, + _reset_rx: broadcast::Receiver<()>, } impl App { @@ -64,6 +70,8 @@ impl App { let redis = Redis::new(config.redis)?; + let (reset_tx, reset_rx) = broadcast::channel(1); + Ok(App { connections, nc_client, @@ -72,6 +80,8 @@ impl App { storage_mapping, redis, log_handle: Mutex::new(log_handle), + reset_tx, + _reset_rx: reset_rx, }) } @@ -91,6 +101,8 @@ impl App { let redis = Redis::new(config.redis)?; + let (reset_tx, reset_rx) = broadcast::channel(1); + Ok(App { connections, nc_client, @@ -99,28 +111,19 @@ impl App { storage_mapping, redis, log_handle: Mutex::new(log_handle), + reset_tx, + _reset_rx: reset_rx, }) } - pub async fn self_test(&self) -> Result<()> { + pub async fn self_test(&self) -> Result<(), SelfTestError> { let _ = self .storage_mapping .get_users_for_storage_path(1, "") - .await - .wrap_err("Failed to test database access")?; - let mut redis = self - .redis - .connect() - .await - .wrap_err("Failed to connect to redis")?; - redis - .del("notify_push_app_version") - .await - .wrap_err("Failed to clear app version")?; - self.nc_client - .request_app_version() - .await - .wrap_err("Failed to request app version")?; + .await?; + let mut redis = self.redis.connect().await?; + redis.del("notify_push_app_version").await?; + self.nc_client.request_app_version().await?; match redis.get("notify_push_app_version").await { Ok(version) if version == env!("NOTIFY_PUSH_VERSION") => {} Ok(version) => { @@ -138,7 +141,11 @@ impl App { async fn handle_event(&self, event: Event) { match event { - Event::StorageUpdate(StorageUpdate { storage, path }) => { + Event::StorageUpdate(StorageUpdate { + storage, + path, + file_id, + }) => { match self .storage_mapping .get_users_for_storage_path(storage, &path) @@ -147,7 +154,7 @@ impl App { Ok(users) => { for user in users { self.connections - .send_to_user(&user, MessageType::File) + .send_to_user(&user, PushMessage::File(file_id.into())) .await; } } @@ -156,12 +163,12 @@ impl App { } Event::GroupUpdate(GroupUpdate { user, .. }) => { self.connections - .send_to_user(&user, MessageType::File) + .send_to_user(&user, PushMessage::File(UpdatedFiles::Unknown)) .await; } Event::ShareCreate(ShareCreate { user }) => { self.connections - .send_to_user(&user, MessageType::File) + .send_to_user(&user, PushMessage::File(UpdatedFiles::Unknown)) .await; } Event::TestCookie(cookie) => { @@ -169,12 +176,12 @@ impl App { } Event::Activity(Activity { user }) => { self.connections - .send_to_user(&user, MessageType::Activity) + .send_to_user(&user, PushMessage::Activity) .await; } Event::Notification(Notification { user }) => { self.connections - .send_to_user(&user, MessageType::Notification) + .send_to_user(&user, PushMessage::Notification) .await; } Event::PreAuth(PreAuth { user, token }) => { @@ -186,7 +193,7 @@ impl App { body, }) => { self.connections - .send_to_user(&user, MessageType::Custom(message, body)) + .send_to_user(&user, PushMessage::Custom(message, body)) .await; } Event::Config(event::Config::LogSpec(spec)) => { @@ -213,14 +220,26 @@ impl App { } Err(e) => log::warn!("Failed to set metrics: {}", e), }, + Event::Signal(event::Signal::Reset) => { + log::info!("Stopping all open connections"); + if let Err(e) = self.reset_tx.send(()) { + log::warn!("Failed to send reset command to all connections: {}", e); + } + } } } + + pub fn reset_rx(&self) -> broadcast::Receiver<()> { + self.reset_tx.subscribe() + } } pub fn serve( app: Arc, bind: Bind, cancel: oneshot::Receiver<()>, + tls: Option<&TlsConfig>, + max_debounce_time: usize, ) -> Result + Send> { let app = warp::any().map(move || app.clone()); @@ -234,12 +253,16 @@ pub fn serve( .and(remote()) .and(get_forwarded_for()) .map( - |ws: warp::ws::Ws, app, remote: Option, mut forwarded_for: Vec| { + move |ws: warp::ws::Ws, + app, + remote: Option, + mut forwarded_for: Vec| { if let Some(remote) = remote { forwarded_for.push(remote.ip()); } log::debug!("new websocket connection from {:?}", forwarded_for.first()); - ws.on_upgrade(move |socket| handle_user_socket(socket, app, forwarded_for)) + let opts = ConnectionOptions::new(max_debounce_time); + ws.on_upgrade(move |socket| handle_user_socket(socket, app, forwarded_for, opts)) }, ) .with(cors); @@ -334,35 +357,49 @@ pub fn serve( let routes = routes.clone().or(warp::path!("push" / ..).and(routes)); - serve_at(routes, bind, cancel) + serve_at(routes, bind, cancel, tls) } -fn serve_at(filter: F, bind: Bind, cancel: C) -> Result + Send> +fn serve_at( + filter: F, + bind: Bind, + cancel: C, + tls: Option<&TlsConfig>, +) -> Result + Send> where C: Future + Send + Sync + 'static, F: Filter + Clone + Send + Sync + 'static, F::Extract: Reply, { let cancel = cancel.map(|_| ()); - match bind { - Bind::Tcp(addr) => { - let (_, server) = warp::serve(filter).bind_with_graceful_shutdown(addr, cancel); - Ok(Either::Left(server)) + let server = warp::serve(filter); + match (bind, tls) { + (Bind::Tcp(addr), Some(tls)) => { + let (_, server) = server + .tls() + .cert_path(&tls.cert) + .key_path(&tls.key) + .bind_with_graceful_shutdown(addr, cancel); + Ok(Either::Left(Either::Left(server))) } - Bind::Unix(socket_path, permissions) => { + (Bind::Tcp(addr), None) => { + let (_, server) = server.bind_with_graceful_shutdown(addr, cancel); + Ok(Either::Left(Either::Right(server))) + } + (Bind::Unix(socket_path, permissions), tls) => { + if tls.is_some() { + log::warn!("Serving with TLS over a unix socket is not supported"); + } fs::remove_file(&socket_path).ok(); - let listener = UnixListener::bind(&socket_path).wrap_err_with(|| { - format!( - "Failed to setup socket at {}", - socket_path.to_string_lossy() - ) - })?; - fs::set_permissions(&socket_path, PermissionsExt::from_mode(permissions))?; + let listener = UnixListener::bind(&socket_path) + .map_err(|e| SocketError::Bind(e, socket_path.to_string_lossy().to_string()))?; + fs::set_permissions(&socket_path, PermissionsExt::from_mode(permissions)) + .map_err(SocketError::SocketPermissions)?; let stream = UnixListenerStream::new(listener); Ok(Either::Right( - warp::serve(filter) + server .serve_incoming_with_graceful_shutdown(stream, cancel) .map(move |_| { fs::remove_file(&socket_path).ok(); @@ -376,7 +413,7 @@ pub async fn listen_loop(app: Arc, cancel: oneshot::Receiver<()>) { let loop_ = async move { loop { if let Err(e) = listen(app.clone()).await { - eprintln!("Failed to setup redis subscription: {:#}", e); + log::error!("Failed to setup redis subscription: {:#}", e); } log::warn!("Redis server disconnected, reconnecting in 1s"); sleep(Duration::from_secs(1)).await; diff --git a/src/main.rs b/src/main.rs index f7ee889b..4d13e586 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ -use color_eyre::{eyre::WrapErr, Result}; -use flexi_logger::{colored_detailed_format, detailed_format, Logger}; +use flexi_logger::{detailed_format, AdaptiveFormat, Logger, LoggerHandle}; +use miette::{IntoDiagnostic, Result, WrapErr}; use notify_push::config::{Config, Opt}; +use notify_push::error::ConfigError; use notify_push::message::DEBOUNCE_ENABLE; use notify_push::metrics::serve_metrics; -use notify_push::{listen_loop, serve, App}; +use notify_push::{listen_loop, serve, App, Error}; use std::sync::atomic::Ordering; use std::sync::Arc; use structopt::StructOpt; @@ -12,9 +13,8 @@ use tokio::signal::unix::{signal, SignalKind}; use tokio::sync::oneshot; use tokio::task::spawn; -#[tokio::main] -async fn main() -> Result<()> { - color_eyre::install()?; +fn main() -> Result<()> { + miette::set_panic_hook(); let _ = dotenv::dotenv(); let opt: Opt = Opt::from_args(); @@ -23,22 +23,37 @@ async fn main() -> Result<()> { return Ok(()); } let dump_config = opt.dump_config; - let config = Config::from_opt(opt).wrap_err("Failed to parse config")?; + let config = Config::from_opt(opt)?; if dump_config { println!("{:#?}", config); return Ok(()); } - let log_handle = Logger::try_with_str(&config.log_level)? - .log_to_stdout() - .format(if config.no_ansi { - detailed_format - } else { - colored_detailed_format - }) - .start()?; + // initialize the logger before starting the tokio runtime + // this prevents potential issues around getting the local time offset + // which isn't properly tread safe on linux + let log_handle = Logger::try_with_str(&config.log_level) + .map_err(ConfigError::LogLevel)? + .log_to_stdout(); + let log_handle = if config.no_ansi { + log_handle.format_for_stdout(detailed_format) + } else { + log_handle.adaptive_format_for_stdout(AdaptiveFormat::Detailed) + } + .start() + .into_diagnostic() + .wrap_err("Failed to initialize log handler")?; + + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() + .block_on(run(config, log_handle))?; + Ok(()) +} +async fn run(config: Config, log_handle: LoggerHandle) -> Result<()> { let (serve_cancel, serve_cancel_handle) = oneshot::channel(); let (metrics_cancel, metrics_cancel_handle) = oneshot::channel(); let (listen_cancel, listen_cancel_handle) = oneshot::channel(); @@ -54,25 +69,37 @@ async fn main() -> Result<()> { } let bind = config.bind.clone(); + let tls = config.tls.clone(); let metrics_bind = config.metrics_bind.clone(); + let max_debounce_time = config.max_debounce_time; let app = Arc::new(App::new(config, log_handle).await?); if let Err(e) = app.self_test().await { log::error!("Self test failed: {:#}", e); } log::trace!("Listening on {}", bind); - let server = spawn(serve(app.clone(), bind, serve_cancel_handle)?); + let server = spawn(serve( + app.clone(), + bind, + serve_cancel_handle, + tls.as_ref(), + max_debounce_time, + )?); if let Some(metrics_bind) = metrics_bind { log::trace!("Metrics listening {}", metrics_bind); - spawn(serve_metrics(metrics_bind, metrics_cancel_handle)?); + spawn(serve_metrics( + metrics_bind, + metrics_cancel_handle, + tls.as_ref(), + )?); } spawn(listen_loop(app, listen_cancel_handle)); // wait for either a sigint or sigterm - let mut term = signal(SignalKind::terminate())?; - let mut int = signal(SignalKind::interrupt())?; + let mut term = signal(SignalKind::terminate()).map_err(Error::SignalHook)?; + let mut int = signal(SignalKind::interrupt()).map_err(Error::SignalHook)?; select! { _ = term.recv() => (), @@ -87,7 +114,10 @@ async fn main() -> Result<()> { metrics_cancel.send(()).ok(); listen_cancel.send(()).ok(); - server.await?; + server + .await + .into_diagnostic() + .wrap_err("Error while running warp server")?; Ok(()) } diff --git a/src/message.rs b/src/message.rs index 641fef80..14f57dd9 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,15 +1,52 @@ +use crate::connection::ConnectionOptions; use parse_display::Display; use serde_json::Value; +use smallvec::SmallVec; +use std::cmp::{max, min}; use std::fmt::Write; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Instant; use tokio::time::Duration; use warp::ws::Message; -#[derive(Debug, Clone, Display)] -pub enum MessageType { +#[derive(Debug, Clone, PartialEq)] +pub enum UpdatedFiles { + Unknown, + Known(SmallVec<[u64; 4]>), +} + +impl UpdatedFiles { + pub fn extend(&mut self, more: &UpdatedFiles) { + match (self, more) { + (UpdatedFiles::Known(items), UpdatedFiles::Known(b)) => { + for id in b { + if !items.contains(id) { + items.push(*id); + } + } + } + (self_, _) => *self_ = UpdatedFiles::Unknown, + } + } +} + +impl From> for UpdatedFiles { + fn from(id: Option) -> Self { + match id { + Some(id) => { + let mut ids = SmallVec::new(); + ids.push(id); + UpdatedFiles::Known(ids) + } + None => UpdatedFiles::Unknown, + } + } +} + +#[derive(Debug, Clone, Display, PartialEq)] +pub enum PushMessage { #[display("notify_file")] - File, + File(UpdatedFiles), #[display("notify_activity")] Activity, #[display("notify_notification")] @@ -18,14 +55,42 @@ pub enum MessageType { Custom(String, Value), } -impl From for Message { - fn from(msg: MessageType) -> Self { - match msg { - MessageType::File => Message::text(String::from("notify_file")), - MessageType::Activity => Message::text(String::from("notify_activity")), - MessageType::Notification => Message::text(String::from("notify_notification")), - MessageType::Custom(ty, Value::Null) => Message::text(ty), - MessageType::Custom(ty, body) => Message::text({ +impl PushMessage { + pub fn merge(&mut self, other: &PushMessage) { + if let (PushMessage::File(a), PushMessage::File(b)) = (self, other) { + a.extend(b) + } + } + + pub fn debounce_time(&self, connection_count: usize, max_debounce_time: usize) -> Duration { + // scale the debounce time between 1s and 15s based on the number of active connections + // this provide a decent balance between performance and load + let time = max(1, min(connection_count / 10, max_debounce_time)); + match self { + PushMessage::File(_) => Duration::from_secs(time as u64), + PushMessage::Activity => Duration::from_secs(time as u64), + PushMessage::Notification => Duration::from_secs(1), + PushMessage::Custom(..) => Duration::from_millis(1), // no debouncing for custom messages + } + } +} + +impl PushMessage { + pub fn into_message(self, opts: &ConnectionOptions) -> Message { + match self { + PushMessage::File(ids) => match ids { + UpdatedFiles::Known(ids) if opts.listen_file_id.load(Ordering::Relaxed) => { + Message::text(format!( + "notify_file_id {}", + serde_json::to_string(&ids).unwrap() + )) + } + _ => Message::text(String::from("notify_file")), + }, + PushMessage::Activity => Message::text(String::from("notify_activity")), + PushMessage::Notification => Message::text(String::from("notify_notification")), + PushMessage::Custom(ty, Value::Null) => Message::text(ty), + PushMessage::Custom(ty, body) => Message::text({ let mut str = ty; write!(&mut str, " {}", body).ok(); str @@ -36,63 +101,217 @@ impl From for Message { pub static DEBOUNCE_ENABLE: AtomicBool = AtomicBool::new(true); -pub struct DebounceMap { - file: Instant, - activity: Instant, - notification: Instant, +#[derive(Clone, Debug)] +struct SendQueueItem { + received: Instant, + sent: Instant, + message: Option, } -impl Default for DebounceMap { +impl Default for SendQueueItem { fn default() -> Self { - let past = Instant::now() - Duration::from_secs(600); - DebounceMap { - file: past, - activity: past, - notification: past, + SendQueueItem { + received: Instant::now() - Duration::from_secs(120), + sent: Instant::now() - Duration::from_secs(120), + message: None, } } } -impl DebounceMap { - /// Check if the debounce time has passed and set the last send time if so - pub fn should_send(&mut self, ty: &MessageType) -> bool { - if DEBOUNCE_ENABLE.load(Ordering::Relaxed) { - let last_send = self.get_last_send(ty); - if Instant::now().duration_since(last_send) > Self::get_debounce_time(ty) { - self.set_last_send(ty); - true - } else { - false - } - } else { - true - } +#[derive(Default, Debug)] +pub struct SendQueue { + items: [SendQueueItem; 3], +} + +impl SendQueue { + pub fn new() -> Self { + SendQueue::default() } - fn get_last_send(&self, ty: &MessageType) -> Instant { - match ty { - MessageType::File => self.file, - MessageType::Activity => self.activity, - MessageType::Notification => self.notification, - MessageType::Custom(..) => Instant::now() - Duration::from_secs(600), // no debouncing for custom messages + fn item_mut(&mut self, message: &PushMessage) -> Option<&mut SendQueueItem> { + match message { + PushMessage::File(_) => Some(&mut self.items[0]), + PushMessage::Activity => Some(&mut self.items[1]), + PushMessage::Notification => Some(&mut self.items[2]), + PushMessage::Custom(_, _) => None, } } - fn set_last_send(&mut self, ty: &MessageType) { - match ty { - MessageType::File => self.file = Instant::now(), - MessageType::Activity => self.activity = Instant::now(), - MessageType::Notification => self.notification = Instant::now(), - MessageType::Custom(..) => {} // no debouncing for custom messages + pub fn push(&mut self, message: PushMessage, time: Instant) -> Option { + if !DEBOUNCE_ENABLE.load(Ordering::Relaxed) { + return Some(message); } + let item = match self.item_mut(&message) { + Some(item) => item, + None => return Some(message), + }; + + match &mut item.message { + Some(queued) => { + queued.merge(&message); + } + opt => { + *opt = Some(message); + } + }; + item.received = time; + + None } - fn get_debounce_time(ty: &MessageType) -> Duration { - match ty { - MessageType::File => Duration::from_secs(5), - MessageType::Activity => Duration::from_secs(15), - MessageType::Notification => Duration::from_secs(1), - MessageType::Custom(..) => Duration::from_millis(1), // no debouncing for custom messages - } + pub fn drain( + &mut self, + now: Instant, + connection_count: usize, + max_debounce_time: usize, + ) -> impl Iterator + '_ { + self.items.iter_mut().filter_map(move |item| { + let debounce_time = item + .message + .as_ref()? + .debounce_time(connection_count, max_debounce_time); + if now.duration_since(item.sent) > debounce_time { + if now.duration_since(item.received) > Duration::from_millis(100) { + item.sent = now; + item.message.take() + } else { + None + } + } else { + None + } + }) } } + +#[test] +fn test_send_queue_100() { + let base_time = Instant::now(); + let mut queue = SendQueue::new(); + queue.push(PushMessage::Activity, base_time); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![1].into())), + base_time, + ); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![2].into())), + base_time + Duration::from_millis(10), + ); + + // within 100ms the messages get merged + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_millis(20), 100, 15) + .collect::>() + ); + + // after 100ms the merged messages get send + assert_eq!( + vec![ + PushMessage::File(UpdatedFiles::Known(vec![1, 2].into())), + PushMessage::Activity + ], + queue + .drain(base_time + Duration::from_millis(200), 100, 15) + .collect::>() + ); + + // messages send within debounce time get held back + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![3].into())), + base_time + Duration::from_secs(5), + ); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![4].into())), + base_time + Duration::from_secs(6), + ); + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_secs(10), 100, 15) + .collect::>() + ); + + // after debounce time we get the merged messages from the timeframe + assert_eq!( + vec![PushMessage::File(UpdatedFiles::Known(vec![3, 4].into()))], + queue + .drain(base_time + Duration::from_secs(70), 100, 15) + .collect::>() + ); + + // nothing left + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_secs(300), 100, 15) + .collect::>() + ); +} + +#[test] +fn test_send_queue_1() { + let base_time = Instant::now(); + let mut queue = SendQueue::new(); + queue.push(PushMessage::Activity, base_time); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![1].into())), + base_time, + ); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![2].into())), + base_time + Duration::from_millis(10), + ); + + // within 100ms the messages get merged + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_millis(20), 1, 15) + .collect::>() + ); + + // after 100ms the merged messages get send + assert_eq!( + vec![ + PushMessage::File(UpdatedFiles::Known(vec![1, 2].into())), + PushMessage::Activity + ], + queue + .drain(base_time + Duration::from_millis(200), 1, 15) + .collect::>() + ); + + // messages send within debounce time get held back + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![3].into())), + base_time + Duration::from_secs_f32(1.2), + ); + queue.push( + PushMessage::File(UpdatedFiles::Known(vec![4].into())), + base_time + Duration::from_secs_f32(1.3), + ); + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_secs(1), 1, 15) + .collect::>() + ); + + // after debounce time we get the merged messages from the timeframe + assert_eq!( + vec![PushMessage::File(UpdatedFiles::Known(vec![3, 4].into()))], + queue + .drain(base_time + Duration::from_secs(3), 1, 15) + .collect::>() + ); + + // nothing left + assert_eq!( + Vec::::new(), + queue + .drain(base_time + Duration::from_secs(5), 1, 15) + .collect::>() + ); +} diff --git a/src/metrics.rs b/src/metrics.rs index 9cd2948b..96f9e9ee 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,6 +1,5 @@ -use crate::config::Bind; -use crate::serve_at; -use color_eyre::Result; +use crate::config::{Bind, TlsConfig}; +use crate::{serve_at, Result}; use serde::{Serialize, Serializer}; use std::fmt::Write; use std::future::Future; @@ -16,7 +15,7 @@ pub struct Metrics { total_connection_count: AtomicUsize, mapping_query_count: AtomicUsize, events_received: AtomicUsize, - messages_send: AtomicUsize, + messages_sent: AtomicUsize, } #[derive(Serialize)] @@ -25,7 +24,7 @@ struct SerializeMetrics { total_connection_count: usize, mapping_query_count: usize, events_received: usize, - messages_send: usize, + messages_sent: usize, } impl From for SerializeMetrics { @@ -35,7 +34,7 @@ impl From for SerializeMetrics { total_connection_count: metrics.total_connection_count(), mapping_query_count: metrics.mapping_query_count(), events_received: metrics.events_received(), - messages_send: metrics.messages_send(), + messages_sent: metrics.messages_sent(), } } } @@ -47,7 +46,7 @@ impl From<&Metrics> for SerializeMetrics { total_connection_count: metrics.total_connection_count(), mapping_query_count: metrics.mapping_query_count(), events_received: metrics.events_received(), - messages_send: metrics.messages_send(), + messages_sent: metrics.messages_sent(), } } } @@ -68,7 +67,7 @@ impl Metrics { total_connection_count: AtomicUsize::new(0), mapping_query_count: AtomicUsize::new(0), events_received: AtomicUsize::new(0), - messages_send: AtomicUsize::new(0), + messages_sent: AtomicUsize::new(0), } } @@ -88,8 +87,8 @@ impl Metrics { self.events_received.load(Ordering::Relaxed) } - pub fn messages_send(&self) -> usize { - self.messages_send.load(Ordering::Relaxed) + pub fn messages_sent(&self) -> usize { + self.messages_sent.load(Ordering::Relaxed) } pub fn add_connection(&self) { @@ -110,13 +109,14 @@ impl Metrics { } pub fn add_message(&self) { - self.messages_send.fetch_add(1, Ordering::Relaxed); + self.messages_sent.fetch_add(1, Ordering::Relaxed); } } pub fn serve_metrics( bind: Bind, cancel: oneshot::Receiver<()>, + tls: Option<&TlsConfig>, ) -> Result + Send> { let metrics = warp::path!("metrics").map(|| { let mut response = String::with_capacity(128); @@ -143,10 +143,10 @@ pub fn serve_metrics( let _ = writeln!( &mut response, "message_count_total {}", - METRICS.messages_send() + METRICS.messages_sent() ); response }); - serve_at(metrics, bind, cancel) + serve_at(metrics, bind, cancel, tls) } diff --git a/src/nc.rs b/src/nc.rs index 0a468897..1f605d65 100644 --- a/src/nc.rs +++ b/src/nc.rs @@ -1,6 +1,6 @@ -use crate::UserId; -use color_eyre::{eyre::WrapErr, Report, Result}; -use reqwest::{StatusCode, Url}; +use crate::error::{AuthenticationError, NextCloudError}; +use crate::{Result, UserId}; +use reqwest::{Response, StatusCode, Url}; use std::fmt::Write; use std::net::IpAddr; @@ -10,8 +10,8 @@ pub struct Client { } impl Client { - pub fn new(base_url: &str, allow_self_signed: bool) -> Result { - let base_url = Url::parse(base_url).wrap_err("Invalid base url")?; + pub fn new(base_url: &str, allow_self_signed: bool) -> Result { + let base_url = Url::parse(base_url)?; let http = reqwest::Client::builder() .danger_accept_invalid_certs(allow_self_signed) .build()?; @@ -23,10 +23,30 @@ impl Client { username: &str, password: &str, forwarded_for: Vec, - ) -> Result { + ) -> Result { log::debug!("Verifying credentials for {}", username); - let response = self - .http + let response = self.auth_request(username, password, forwarded_for).await?; + + match response.status() { + StatusCode::OK => Ok(response + .text() + .await + .map_err(|_| AuthenticationError::InvalidMessage)? + .into()), + StatusCode::UNAUTHORIZED => Err(AuthenticationError::Invalid), + status if status.is_server_error() => Err(NextCloudError::Server(status).into()), + status if status.is_client_error() => Err(NextCloudError::Client(status).into()), + status => Err(NextCloudError::Other(status).into()), + } + } + + async fn auth_request( + &self, + username: &str, + password: &str, + forwarded_for: Vec, + ) -> Result { + self.http .get(self.base_url.join("index.php/apps/notify_push/uid")?) .basic_auth(username, Some(password)) .header( @@ -44,22 +64,10 @@ impl Client { ) .send() .await - .wrap_err("Error while connecting to nextcloud server")?; - - match response.status() { - StatusCode::OK => Ok(response.text().await?.into()), - StatusCode::UNAUTHORIZED => Err(Report::msg("Invalid credentials")), - status if status.is_server_error() => { - Err(Report::msg(format!("Server error: {}", status))) - } - status if status.is_client_error() => { - Err(Report::msg(format!("Client error: {}", status))) - } - status => Err(Report::msg(format!("Unexpected status code: {}", status))), - } + .map_err(NextCloudError::NextcloudConnect) } - pub async fn get_test_cookie(&self) -> Result { + pub async fn get_test_cookie(&self) -> Result { let response = self .http .get( @@ -72,37 +80,39 @@ impl Client { let text = response.text().await?; if status.is_client_error() { if text.contains("admin-trusted-domains") { - Err(Report::msg(format!( - "{} is not configured as a trusted domain", - self.base_url.host_str().unwrap_or_default() - ))) + Err(NextCloudError::NotATrustedDomain( + self.base_url.host_str().unwrap_or_default().into(), + ) + .into()) } else { - Err(Report::msg(status.to_string())) + Err(NextCloudError::Client(status).into()) } } else { Ok(text .parse() - .wrap_err("Response from nextcloud is not a number")?) + .map_err(NextCloudError::MalformedCookieResponse)?) } } - pub async fn test_set_remote(&self, addr: IpAddr) -> Result { + pub async fn test_set_remote(&self, addr: IpAddr) -> Result { Ok(self .http .get( self.base_url - .join("index.php/apps/notify_push/test/remote")?, + .join("index.php/apps/notify_push/test/remote") + .map_err(NextCloudError::from)?, ) .header("x-forwarded-for", addr.to_string()) .send() .await? .text() .await? - .parse()?) + .parse() + .map_err(NextCloudError::MalformedRemote)?) } /// Ask the app to put it's version number into redis under 'notify_push_app_version' - pub async fn request_app_version(&self) -> Result<()> { + pub async fn request_app_version(&self) -> Result<(), NextCloudError> { self.http .get( self.base_url diff --git a/src/redis.rs b/src/redis.rs index 02875ce8..58e0dd5c 100644 --- a/src/redis.rs +++ b/src/redis.rs @@ -1,7 +1,8 @@ -use color_eyre::{Report, Result}; +use crate::error::ConfigError; +use crate::Result; use redis::aio::{Connection, PubSub}; use redis::cluster::{ClusterClient, ClusterConnection}; -use redis::{AsyncCommands, Client, Commands, ConnectionInfo}; +use redis::{AsyncCommands, Client, Commands, ConnectionInfo, RedisError}; use tokio::task::block_in_place; pub struct Redis { @@ -11,20 +12,20 @@ pub struct Redis { impl Redis { pub fn new(config: Vec) -> Result { if config.is_empty() { - return Err(Report::msg("No redis server configured")); + return Err(ConfigError::NoRedis.into()); } Ok(Redis { config }) } /// Get an async pubsub connection - pub async fn pubsub(&self) -> Result { + pub async fn pubsub(&self) -> Result { // since pubsub performs a multicast for all nodes in a cluster, // listening to a single server in the cluster is sufficient for cluster setups let client = Client::open(self.config.first().unwrap().clone())?; Ok(client.get_async_connection().await?.into_pubsub()) } - pub async fn connect(&self) -> Result { + pub async fn connect(&self) -> Result { let connection = match self.config.as_slice() { [single] => { let client = Client::open(single.clone())?.get_async_connection().await?; @@ -32,7 +33,7 @@ impl Redis { } config => { let client = - block_in_place(|| ClusterClient::open(config.to_vec())?.get_connection())?; + block_in_place(|| ClusterClient::new(config.to_vec())?.get_connection())?; RedisConnection::Cluster(client) } }; @@ -46,7 +47,7 @@ pub enum RedisConnection { } impl RedisConnection { - pub async fn del(&mut self, key: &str) -> Result<()> { + pub async fn del(&mut self, key: &str) -> Result<(), redis::RedisError> { match self { RedisConnection::Async(client) => { client.del::<_, ()>(key).await?; diff --git a/src/storage_mapping.rs b/src/storage_mapping.rs index 5c034da4..7cb97e94 100644 --- a/src/storage_mapping.rs +++ b/src/storage_mapping.rs @@ -1,7 +1,9 @@ +use crate::error::DatabaseError; use crate::metrics::METRICS; -use crate::UserId; -use color_eyre::{eyre::WrapErr, Result}; +use crate::{Result, UserId}; +use dashmap::mapref::one::Ref; use dashmap::DashMap; +use log::debug; use rand::{thread_rng, Rng}; use sqlx::any::AnyConnectOptions; use sqlx::{Any, AnyPool, FromRow}; @@ -43,7 +45,10 @@ pub struct StorageMapping { } impl StorageMapping { - pub async fn from_connection(connection: AnyPool, prefix: String) -> Result { + pub async fn from_connection( + connection: AnyPool, + prefix: String, + ) -> Result { Ok(StorageMapping { cache: Default::default(), connection, @@ -51,33 +56,34 @@ impl StorageMapping { }) } - pub async fn new(options: AnyConnectOptions, prefix: String) -> Result { + pub async fn new(options: AnyConnectOptions, prefix: String) -> Result { let connection = AnyPool::connect_with(options) .await - .wrap_err("Failed to connect to Nextcloud database")?; + .map_err(DatabaseError::Connect)?; Self::from_connection(connection, prefix).await } - pub async fn get_users_for_storage_path<'a>( + async fn get_storage_mapping( &self, storage: u32, - path: &str, - ) -> Result> { - let cached = if let Some(cached) = self.cache.get(&storage).and_then(|cached| { - if cached.is_valid() { - Some(cached) - } else { - None - } - }) { - cached + ) -> Result, DatabaseError> { + if let Some(cached) = self.cache.get(&storage).filter(|cached| cached.is_valid()) { + Ok(cached) } else { let users = self.load_storage_mapping(storage).await?; self.cache.insert(storage, CachedAccess::new(users)); - self.cache.get(&storage).unwrap() - }; + Ok(self.cache.get(&storage).unwrap()) + } + } + + pub async fn get_users_for_storage_path( + &self, + storage: u32, + path: &str, + ) -> Result, DatabaseError> { + let cached = self.get_storage_mapping(storage).await?; Ok(cached .access .iter() @@ -92,8 +98,11 @@ impl StorageMapping { .into_iter()) } - async fn load_storage_mapping(&self, storage: u32) -> Result> { - log::debug!("querying storage mapping for {}", storage); + async fn load_storage_mapping( + &self, + storage: u32, + ) -> Result, DatabaseError> { + debug!("querying storage mapping for {}", storage); let users = sqlx::query_as::(&format!( "\ SELECT user_id, path \ @@ -105,9 +114,11 @@ impl StorageMapping { )) .fetch_all(&self.connection) .await - .wrap_err("Failed to load storage mapping from database")?; + .map_err(DatabaseError::Query)?; METRICS.add_mapping_query(); + debug!("got storage mappings for {}: {:?}", storage, users); + Ok(users) } } diff --git a/src/user.rs b/src/user.rs index d37b2825..f8b6d630 100644 --- a/src/user.rs +++ b/src/user.rs @@ -9,11 +9,12 @@ use sqlx::error::BoxDynError; use sqlx::{Database, Decode, Type}; use std::collections::hash_map::DefaultHasher; use std::fmt; +use std::fmt::Formatter; use std::hash::Hasher; static USER_NAMES: Lazy> = Lazy::new(DashMap::default); -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] pub struct UserId { hash: u64, } @@ -107,3 +108,17 @@ impl fmt::Display for UserId { } } } + +impl fmt::Debug for UserId { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if log::max_level() >= LevelFilter::Info { + if let Some(user_name) = USER_NAMES.get(&self.hash) { + write!(f, "{}(#{})", user_name.value(), self.hash) + } else { + write!(f, "user #{}", self.hash) + } + } else { + write!(f, "user #{} (Set log level to INFO or higher)", self.hash) + } + } +} diff --git a/test_client/Cargo.toml b/test_client/Cargo.toml index 542c6139..bfdb409b 100644 --- a/test_client/Cargo.toml +++ b/test_client/Cargo.toml @@ -5,10 +5,11 @@ authors = ["Robin Appelman "] edition = "2018" [dependencies] -tungstenite = { version = "0.14", default-features = false, features = ["rustls-tls"] } -color-eyre = "0.5" -serde_json = "1" -ureq = "2" -flexi_logger = { version = "0.18", features = ["colors"] } -log = "0.4" -base64 = "0.13" \ No newline at end of file +tungstenite = { version = "0.19.0", features = ["rustls-tls-webpki-roots"] } +serde_json = "1.0.96" +ureq = "2.6.2" +flexi_logger = { version = "0.25.3", features = ["colors"] } +log = "0.4.17" +base64 = "0.21.0" +miette = { version = "5.8.0", features = ["fancy"] } +url = "2.3.1" diff --git a/test_client/src/main.rs b/test_client/src/main.rs index aab78efa..c7b269d9 100644 --- a/test_client/src/main.rs +++ b/test_client/src/main.rs @@ -1,13 +1,19 @@ -use color_eyre::{eyre::WrapErr, Report, Result}; -use flexi_logger::Logger; +use base64::Engine; +use flexi_logger::{AdaptiveFormat, Logger}; +use log::{debug, info, trace, warn}; +use miette::{IntoDiagnostic, Report, Result, WrapErr}; use serde_json::Value; use std::env::var; -use tungstenite::http::Request; use tungstenite::{connect, Message}; +use url::Url; fn main() -> Result<()> { - color_eyre::install()?; - Logger::try_with_str(&var("LOG").unwrap_or_else(|_| String::from("warn")))?.start()?; + Logger::try_with_str(&var("LOG").unwrap_or_else(|_| String::from("test_client=info,warn"))) + .into_diagnostic()? + .adaptive_format_for_stdout(AdaptiveFormat::Detailed) + .adaptive_format_for_stderr(AdaptiveFormat::Detailed) + .start() + .into_diagnostic()?; let mut args = std::env::args(); @@ -20,36 +26,48 @@ fn main() -> Result<()> { } }; - let ws_url = get_endpoint(&nc_url, &username, &password)?; - println!("Found push server at {}", ws_url); + let ws_url = if nc_url.starts_with("ws") { + nc_url + } else { + get_endpoint(&nc_url, &username, &password)? + }; + info!("Found push server at {}", ws_url); - let ws_request = Request::get(ws_url) - .body(()) + let ws_url = Url::parse(&ws_url) + .into_diagnostic() .wrap_err("Invalid websocket url")?; - let (mut socket, _response) = connect(ws_request).wrap_err("Can't connect to server")?; + let (mut socket, _response) = connect(ws_url) + .into_diagnostic() + .wrap_err("Can't connect to server")?; socket .write_message(Message::Text(username)) + .into_diagnostic() .wrap_err("Failed to send username")?; socket .write_message(Message::Text(password)) + .into_diagnostic() .wrap_err("Failed to send password")?; + socket + .write_message(Message::Text("listen notify_file_id".into())) + .into_diagnostic() + .wrap_err("Failed to send username")?; loop { - if let Message::Text(text) = socket.read_message()? { + if let Message::Text(text) = socket.read_message().into_diagnostic()? { if text.starts_with("err: ") { - eprintln!("Received error: {}", &text[5..]); + warn!("Received error: {}", &text[5..]); return Ok(()); - } else if text == "notify_file" { - println!("Received file update notification"); + } else if text.starts_with("notify_file") { + info!("Received file update notification {}", text); } else if text == "notify_activity" { - println!("Received activity notification"); + info!("Received activity notification"); } else if text == "notify_notification" { - println!("Received notification notification"); + info!("Received notification notification"); } else if text == "authenticated" { - println!("Authenticated"); + info!("Authenticated"); } else { - println!("Received: {}", text); + info!("Received: {}", text); } } } @@ -61,18 +79,21 @@ fn get_endpoint(nc_url: &str, user: &str, password: &str) -> Result { "Authorization", &format!( "Basic {}", - base64::encode(&format!("{}:{}", user, password)) + base64::engine::general_purpose::STANDARD.encode(&format!("{}:{}", user, password)) ), ) .set("Accept", "application/json") .set("OCS-APIREQUEST", "true") - .call()? - .into_string()?; - log::debug!("Capabilities response: {}", raw); + .call() + .into_diagnostic()? + .into_string() + .into_diagnostic()?; + trace!("Capabilities response: {}", raw); let json: Value = serde_json::from_str(&raw) + .into_diagnostic() .wrap_err_with(|| format!("Failed to decode json capabilities response: {}", raw))?; if let Some(capabilities) = json["ocs"]["data"]["capabilities"].as_object() { - log::info!( + debug!( "Supported capabilities: {:?}", capabilities.keys().collect::>() ); diff --git a/tests/CoreEventsTest.php b/tests/CoreEventsTest.php new file mode 100644 index 00000000..c9378c79 --- /dev/null +++ b/tests/CoreEventsTest.php @@ -0,0 +1,121 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\NotifyPush\Tests; + +use OC\Files\Storage\Temporary; +use OCA\NotifyPush\AppInfo\Application; +use OCA\NotifyPush\Listener; +use OCA\NotifyPush\Queue\IQueue; +use OCP\Activity\IManager as IActivityManager; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IGroupManager; +use OCP\IUserManager; +use OCP\Notification\IManager as INotificationManager; +use Test\TestCase; + +/** + * @group DB + */ +class CoreEventsTest extends TestCase { + private function getListener(array &$events) { + $queue = $this->createMock(IQueue::class); + $queue->method('push')->willReturnCallback(function ($channel, $event) use (&$events) { + if (!isset($events[$channel])) { + $events[$channel] = []; + } + $events[$channel][] = $event; + }); + $listener = new Listener($queue); + $app = \OC::$server->get(Application::class); + $app->attachHooks(\OC::$server->get(IEventDispatcher::class), $listener, \OC::$server->get(IActivityManager::class), \OC::$server->get(INotificationManager::class)); + return $listener; + } + + public function testFilesystemEvents() { + $storage = new Temporary([]); + $cache = $storage->getCache(); + $scanner = $storage->getScanner(); + + $storage->mkdir('foobar'); + $scanner->scan(''); + + $events = []; + $this->getListener($events); + + $storage->touch('foobar', 100); + $storage->getUpdater()->update('foobar'); + + // file ids are unstable, so we remove them + foreach ($events['notify_storage_update'] as &$event) { + unset($event['file_id']); + } + + $this->assertEquals([ + 'notify_storage_update' => [ + ['storage' => $cache->getNumericStorageId(), 'path' => 'foobar'], + ['storage' => $cache->getNumericStorageId(), 'path' => 'foobar'], + ['storage' => $cache->getNumericStorageId(), 'path' => ''], + ], + ], $events); + } + + public function testGroupEvents() { + $userManager = \OC::$server->get(IUserManager::class); + $groupManager = \OC::$server->get(IGroupManager::class); + $uid = uniqid('user_'); + $gid = uniqid('user_'); + + $groupManager->createGroup($gid); + $userManager->createUser($uid, 'a'); + $group = $groupManager->get($gid); + $user = $userManager->get($uid); + + $events = []; + $this->getListener($events); + + $group->addUser($user); + + $this->assertEquals([ + 'notify_group_membership_update' => [ + ['user' => $uid, 'group' => $gid], + ], + 'notify_activity' => [ + ['user' => $uid], + ], + ], $events); + + $events = []; + + $group->removeUser($user); + + $this->assertEquals([ + 'notify_group_membership_update' => [ + ['user' => $uid, 'group' => $gid], + ], + 'notify_activity' => [ + ['user' => $uid], + ], + ], $events); + } +} diff --git a/tests/ListenerTest.php b/tests/ListenerTest.php new file mode 100644 index 00000000..3557587a --- /dev/null +++ b/tests/ListenerTest.php @@ -0,0 +1,128 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\NotifyPush\Tests; + +use OCA\NotifyPush\Listener; +use OCA\NotifyPush\Queue\IQueue; +use OCP\Files\Cache\CacheEntryInsertedEvent; +use OCP\Files\Storage\IStorage; +use OCP\Group\Events\UserAddedEvent; +use OCP\Group\Events\UserRemovedEvent; +use OCP\IGroup; +use OCP\IUser; +use OCP\Share\Events\ShareCreatedEvent; +use OCP\Share\IShare; +use Test\TestCase; + +class ListenerTest extends TestCase { + private function getQueue(array &$events) { + $queue = $this->createMock(IQueue::class); + $queue->method('push')->willReturnCallback(function ($channel, $event) use (&$events) { + if (!isset($events[$channel])) { + $events[$channel] = []; + } + $events[$channel][] = $event; + }); + return $queue; + } + + public function testCacheEvents() { + $events = []; + $queue = $this->getQueue($events); + $listener = new Listener($queue); + + $listener->cacheListener(new CacheEntryInsertedEvent( + $this->createMock(IStorage::class), + 'foobar', + 12, + 1 + )); + + // file ids are unstable, so we remove them + foreach ($events['notify_storage_update'] as &$event) { + unset($event['file_id']); + } + + $this->assertEquals([ + 'notify_storage_update' => [ + ['storage' => 1, 'path' => 'foobar'], + ], + ], $events); + } + + public function testGroupEvents() { + $events = []; + $queue = $this->getQueue($events); + $listener = new Listener($queue); + + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('user1'); + + $group = $this->createMock(IGroup::class); + $group->method('getGID')->willReturn('group1'); + + $listener->groupListener(new UserAddedEvent( + $group, + $user + )); + $this->assertEquals([ + 'notify_group_membership_update' => [ + ['user' => 'user1', 'group' => 'group1'], + ], + ], $events); + + $events = []; + + $listener->groupListener(new UserRemovedEvent( + $group, + $user + )); + $this->assertEquals([ + 'notify_group_membership_update' => [ + ['user' => 'user1', 'group' => 'group1'], + ], + ], $events); + } + + public function testShareEvents() { + $events = []; + $queue = $this->getQueue($events); + $listener = new Listener($queue); + + $share = $this->createMock(IShare::class); + $share->method('getShareType') + ->willReturn(IShare::TYPE_USER); + $share->method('getSharedWith') + ->willReturn('user1'); + + $listener->shareListener(new ShareCreatedEvent( + $share + )); + $this->assertEquals([ + 'notify_user_share_created' => [ + ['user' => 'user1'], + ], + ], $events); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..57d26176 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,12 @@ +addPsr4('Test\\', OC::$SERVERROOT . '/tests/lib/', true); +\OC::$composerAutoloader->addPsr4('Tests\\', OC::$SERVERROOT . '/tests/', true); + +OC_App::loadApp('notify_push'); + +OC_Hook::clear(); diff --git a/tests/integration.rs b/tests/integration.rs index 7f6b2039..1de3353e 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -5,12 +5,14 @@ use futures::{pin_mut, FutureExt}; use futures::{SinkExt, StreamExt}; use http_auth_basic::Credentials; use notify_push::config::{Bind, Config}; +use notify_push::message::DEBOUNCE_ENABLE; use notify_push::{listen_loop, serve, App}; use once_cell::sync::Lazy; use redis::AsyncCommands; use smallvec::alloc::sync::Arc; use sqlx::AnyPool; use std::net::SocketAddr; +use std::sync::atomic::Ordering; use std::sync::Mutex; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::oneshot; @@ -28,12 +30,9 @@ static LAST_PORT: Lazy> = Lazy::new(|| Mutex::new(1024)); async fn listen_available_port() -> Option { let mut last_port = LAST_PORT.lock().unwrap(); for port in (*last_port + 1)..65535 { - match TcpListener::bind(("127.0.0.1", port)).await { - Ok(tcp) => { - *last_port = port; - return Some(tcp); - } - _ => {} + if let Ok(tcp) = TcpListener::bind(("127.0.0.1", port)).await { + *last_port = port; + return Some(tcp); } } @@ -54,6 +53,7 @@ static LOG_HANDLE: Lazy = impl Services { pub async fn new() -> Self { + DEBOUNCE_ENABLE.store(false, Ordering::SeqCst); let redis_tcp = listen_available_port() .await .expect("Can't find open port for redis"); @@ -151,9 +151,11 @@ impl Services { nextcloud_url: format!("http://{}/", self.nextcloud), metrics_bind: None, log_level: "".to_string(), - bind: Bind::Tcp(self.nextcloud.clone()), + bind: Bind::Tcp(self.nextcloud), allow_self_signed: false, no_ansi: false, + tls: None, + max_debounce_time: 15, } } @@ -178,7 +180,7 @@ impl Services { let bind = Bind::Tcp(addr); spawn(async move { - let serve = serve(app.clone(), bind, serve_rx).unwrap(); + let serve = serve(app.clone(), bind, serve_rx, None, 15).unwrap(); let listen = listen_loop(app.clone(), listen_rx); pin_mut!(serve); @@ -285,11 +287,11 @@ async fn test_auth_failure() { assert_next_message(&mut client, "err: Invalid credentials").await; } -#[track_caller] async fn assert_next_message( client: &mut WebSocketStream>, expected: &str, ) { + sleep(Duration::from_millis(100)).await; assert_eq!( timeout(Duration::from_millis(200), client.next()) .await @@ -300,7 +302,6 @@ async fn assert_next_message( ); } -#[track_caller] async fn assert_no_message(client: &mut WebSocketStream>) { sleep(Duration::from_millis(5)).await; assert!(timeout(Duration::from_millis(10), client.next()) @@ -429,6 +430,8 @@ async fn test_pre_auth() { let server_handle = services.spawn_server().await; + sleep(Duration::from_millis(500)).await; + let mut redis = services.redis_client().await; redis .publish::<_, _, ()>("notify_pre_auth", r#"{"user":"foo", "token": "token"}"#) diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 00000000..e398b674 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,20 @@ + + + + . + + + + ../ + + ../tests + + + + + diff --git a/tests/stub.phpstub b/tests/stub.phpstub index 21324377..3d8d8c0e 100644 --- a/tests/stub.phpstub +++ b/tests/stub.phpstub @@ -53,3 +53,13 @@ namespace OC\Files\Cache { } } + +namespace OC\Files\Storage\Wrapper { + + use OCP\Files\Storage\IStorage; + + interface Jail extends IStorage { + public function getUnjailedPath(string $path): string; + public function getUnjailedStorage(): IStorage; + } +}